I produce the following node and relationship data in a for loop about 1 million times. The idea is that investor nodes connect to company nodes by relationship edges:
investor = {'name': owner['name'],
'CIK': owner['CIK']}
relationship = {'isDirector': owner['isDirector'],
'isOfficer': owner['isOfficer'],
'isOther': owner['isOther'],
'isTenPercentOwner': owner['isTenPercentOwner'],
'title': owner['title']}
company = {'Name': json['issuerName'],
'SIC': json['issuerSIC'],
'Ticker Symbol': json['issuerTradingSymbol'],
'CIK': json['issuerCIK'],
'EIN': json['issuerEIN']}
How do I complete the following code to get the dicts above into neo4j community edition?
from py2neo import Graph, authenticate
authenticate("localhost:7474", "neo4j", "neo")
graph = Graph()
for json in long_list_of_dicts:
investor = {...}
company = {...}
relationship = {...}
# Code to import investor, company, relationship data into neo4j
In py2neo a Node is defined in following manner:
class Node(*labels, **properties)
Each node has a label and can have many properties. In this case, Investor node can de defined by setting the label investor and properties of the node to be name and CIK.
investor_node = Node('investor', name = owner['name'], CIK = owner['CIK'])
Similarly, company node would look like:
company_node = Node('company', name = json['issuerName'], SIC = json['issuerSIC'])
Relationship are defined in following manner :
class Relationship(start_node, type, end_node, **properties)
In this case Relationship can be defined using:
investor_company_relationship = Relationship(investor_node, "is_director", company_node)
You can find one sample implementation of neo4j graph here.
You could use UNWIND clause. Something like
WITH {json} AS document
UNWIND document AS company
MERGE (c:company {c_id:company.id})
SET c.sic=company.issuerSIC
If some of your json items is list again, you can use UNWIND as much as you like: UNWIND document.list_of_some_property
Related
I'm customizing the Odoo project module, in the module, we have Projects that have tasks assigned to employees, I need to have a dropdown of employees based on the project selection, but because there isn't a direct relation I have to search all the tasks related to the project and then search for the employees.
this is my model so far:
class myModel(models.TransientModel):
_name = "mymodule.mymodel"
project_id = fields.Many2one('project.project', string="Project")
task_id = fields.Many2one('project.task', string="Task", domain="[('project_id', '=', project_id)]")
employee_id = fields.Many2one('hr.employee', string="Assign To")
#api.onchange('project_id')
def _projecy_onchange(self):
if not self.project_id.id:
return {'domain': {'employee_id': []}}
tasks = self.env['project.task'].search([('project_id','=',self.project_id.id)])
user_ids = []
for t in tasks:
if t.user_id:
user_ids.append(t.user_id.id)
if len(user_ids)>0:
employees = self.env['hr.employee'].search(['user_id','in', user_ids])
return {'domain': {'employee_id': employees}}
else:
return {'domain': {'employee_id': []}}
I'm having an issue when I want to search the employees:
employees = self.env['hr.employee'].search(['user_id','in',
user_ids])
I get the following error:
elif token[1] == 'in' and not token[2]: IndexError: tuple index out
of range
when I print user_ids is a basic list with the ids something like [9] (single element, cloud me more obviously)
I understand search can work as
employees = self.env['hr.employee'].search(['user_id','in', [9])
any guidance will be appreciated
You have got the wrong syntax of odoo's search method do it like this,
employees = self.env['hr.employee'].search([('user_id','in', user_ids)])
Missing part from your syntax: round braces around your domain.
I have the following neo4j models with a Document and Text relationship, where multiple texts are linked to a document :
class Document(StructuredNode):
"""Document Neo4J model for documents"""
document_id = IntegerProperty(required = True)
class Text(StructuredNode):
"""Text model for managing texts"""
# Inherent text properties
text_id = IntegerProperty(required = True)
text = StringProperty(required = True)
document = RelationshipTo('Document', "PARENT")
In order to fetch ALL the Text objects linked with a specific document, I am using traversal as follows :
def get_all_texts_by_document_id(document_id):
document = Document.nodes.get_or_none(document_id = document_id)
definition = dict(node_class = Text, direction = EITHER, relation_type = "PARENT", model = None)
document_to_text_traversal = Traversal(document, Text.__label__, definition)
texts = document_to_text_traversal.all()
print(f"Returning {len(texts)} texts for document_id {document_id}")
return texts
I want to fetch a text with specific text ID and currently I am iterating with an if condition over the list of all the texts received using the above function.
Is there an inbuilt method / better way to filter on the basis of text_id once the traversal is done ?
I am not aware of any way to filter nodes after traversal with neomodel.
However, if you do not have to use Traversal objects, you could use something like this:
add the relationship from Text to Document by adding this line to your Document class:
texts = RelationshipFrom('Text', "PARENT")
Follow the PARENT relationship and filter on the end nodes:
document = Document.nodes.get_or_none(document_id=1)
if document:
texts = document.texts.filter(text_id=1)
print(texts.all())
I'm starting working with an existing database where attribute foo of table A is related to more then one other table, B.foo and C.foo. How do I form this relationship in ponyorm?
The database is organized like below.
from pony import orm
db = orm.Database()
class POI(db.Entity):
'''Point of interest on a map'''
name = orm.PrimaryKey(str)
coordinateID = orm.Optional(('cartesian', 'polar')) # doesn't work ofc
class cartesian(db.Entity):
coordinateID = orm.Required(POI)
x = orm.Required(float)
y = orm.Required(float)
class polar(db.Entity):
coordinateID = orm.Required(POI)
r = orm.Required(float)
phi = orm.Required(float)
Of course x,y from cartesian and r,phi from polar could be moved to POI, and in the database I work with, that's the same situation. But the tables are divided up between stakeholders (cartesian and polar in this example) and I don't get to change the schema anyway. I can't split coordinateID in the schema (but it would actually be nice to have different attributes of the python class).
It is not possible to relate one attribute for several enties in PonyORM except for the case when these entities are inherited from the same base entity, then you can specify base entity as the attribute type and use any of inherited entity as a real type.
If you use existing schema that you can't change, you probably can't use inheritance and need to specify raw id attribute instead of relationship:
from pony import orm
db = orm.Database()
class POI(db.Entity):
_table_ = "table_name"
name = orm.PrimaryKey(str)
coordinate_id = orm.Optional(int, column="coordinateID")
class Cartesian(db2.Entity):
_table_ = "cartesian"
id = orm.PrimaryKey(int, column="coordinateID")
x = orm.Required(float)
y = orm.Required(float)
class Polar(db2.Entity):
_table_ = "polar"
id = orm.PrimaryKey(int, column="coordinateID")
r = orm.Required(float)
phi = orm.Required(float)
And then you can perform queries like this:
left_join(poi for poi in POI
for c in Cartesian
for p in Polar
if poi.coordinate_id == c.id
and poi.coordinate_id = p.id
and <some additional conditions>)
Note that all entities used in the same query should be from the same database. If entities belongs to two different databases, you cannot use them in the same query. And need to issue separate queries:
with db_session:
poi = POI.get(id=some_id)
coord = Cartesian.get(id=poi.coordinate_id)
if coord is None:
coord = Polar.get(id=poi.coordinate_id)
<do something with poi and coord>
But in case, for example, of SQLite you can attach one database to another to make them appear as a single database.
I have the following code:
import py2neo
from py2neo import Graph, Node, Relationship
def createRelationshipWithProperties():
print("Start - Creating Relationships")
# Authenticate the user using py2neo.authentication
# Ensure that you change the password 'sumit' as per your database configuration.
py2neo.authenticate("localhost:7474", "neo4j", "")
# Connect to Graph and get the instance of Graph
graph = Graph("http://localhost:7474/db/data/")
# Create Node with Properties
amy = Node("FEMALE", name="Amy")
# Create one more Node with Properties
kristine = Node("FEMALE",name="Kristine")
# Create one more Node with Properties
sheryl = Node("FEMALE",name="Sheryl")
kristine_amy = Relationship(kristine,"FRIEND",amy,since=2005)
print (kristine_amy)
amy_sheryl = Relationship(sheryl,("FRIEND"),amy,since=2001)
#Finally use graph Object and Create Nodes and Relationship
#When we create Relationship between, then Nodes are also created.
resultNodes = graph.create(kristine_amy)
resultNodes1 = graph.create(amy_sheryl)
#Print the results (relationships)
print("Relationship Created - ",resultNodes)
print("Relationship Created - ",resultNodes1)
if __name__ == '__main__':
createRelationshipWithProperties()
The resultsNodes = graph.create line seems to commit the nodes and relationships to the server because I can see them when I match(n) Return n. However, when the code prints resultsNodes, I get None as if they don't exist. This is the output that I get:
Start - Creating Relationships
(kristine)-[:FRIEND {since:2005}]->(amy)
Relationship Created - None
Relationship Created - None
You're using the API incorrectly. The create method doesn't return nodes but instead updates the supplied argument. Therefore to get the relationship nodes, you need to interrogate the relationship object after performing the create.
I'm using py2neo (version 1.6). I want to get an existing node by its property from the graph and then use it to create a relationship.
My solution:
graph = neo4j.GraphDatabaseService("http://...")
query = neo4j.CypherQuery(graph,"MATCH (n:NodeType) where n.property = 'property' return n")
r = query.execute()
if len(r.data)==0:
raise Exception("node does not exist")
node = r.data[0]['n']
newNode = batch.create(node(name="APropertyOfNewNode"))
batch.add_labels(newNode, "LableOfNewNode")
relation = rel(node, "relationshipName", newNode)
batch.create(relation)
batch.submit()
batch.clear()
Is there an high level way to get an existing node by its property without using CypherQuery and writing plain cypher?
You can use GraphDatabaseService.find:
from py2neo import neo4j
graph = neo4j.GraphDatabaseService('http://localhost:7474/db/data/')
movies = graph.find('Movie', 'title', 'The Matrix')
But graph.find returns a generator object.
movies
# <generator object find at 0x10b64acd0>
So you can only iterate through it once.
for movie in movies:
print type(movie)
print movie['tagline']
# <class 'py2neo.neo4j.Node'>
# Welcome to the Real World