I am loading simple csv data into neo4j. The data is simple as follows :-
uniqueId compound value category
ACT12_M_609 mesulfen 21 carbon
ACT12_M_609 MNAF 23 carbon
ACT12_M_609 nifluridide 20 suphate
ACT12_M_609 sulfur 23 carbon
I am loading the data from the URL using the following query -
LOAD CSV WITH HEADERS
FROM "url"
AS row
MERGE( t: Transaction { transactionId: row.uniqueId })
MERGE(c:Compound {name: row.compound})
MERGE (t)-[r:CONTAINS]->(c)
ON CREATE SET c.category= row.category
ON CREATE SET r.price =row.value
Next I do the aggregation to count total orders for a compound and create property for a node in the following way -
MATCH (c:Compound) <-[:CONTAINS]- (t:Transaction)
with c.name as name, count( distinct t.transactionId) as ord
set c.orders = ord
So far so good. I can accomplish what I want but I have the following 2 questions -
How can I create the orders property for compound node in the first step itself? .i.e. when I am loading the data I would like to perform the aggregation straight away.
For a compound node I am also setting the property for category. Theoretically, it can also be modelled as category -contains-> compound by creating Categorynode. But what advantage will I have if I do it? Because I can execute the queries and get the expected output without creating this additional node.
Thank you for your answer.
I don't think that's possible, LOAD CSV goes over one row at a time, so at row 1, it doesn't know how many more rows will follow.
I guess you could create virtual nodes and relationships, aggregate those and then use those to create the real nodes, but that would be way more complicated. Virtual Nodes/Rels
That depends on the questions/queries you want to ask.
A graph database is optimised for following relationships, so if you often do a query where the category is a criteria (e.g. MATCH (c: Category {category_id: 12})-[r]-(:Compound) ), it might be more performant to create a label for it.
If you just want to get the category in the results (e.g. RETURN compound.category), then it's fine as a property.
I'm using py2neo in Python to run my Cypher queries.
I'm trying to create Person nodes and relationships between then.
My DataFrame is like this:
df
>>> id_user name follows.profiles
a_123 Mc Marcão <3 [a_134, a_934, a_145, a_988]
a_234 john a_111
a_934 alice NaN
: : :
: : :
So here we can see that a Person can follows multiple persons, because follows.profiles is a list.
So this is what I did:
for index, row in df.iterrows():
graph.run('''
UNWIND $label3 as follow_profile
MERGE (p1:Profile { id_user: $label1, name: $label2 })
MERGE (p1)-[:FOLLOWS]->(p2:Profile { id_user: follow_profile })
''', parameters = {'label1': row['id_user'],
'label2': row['name'],
'label3': row['follows.profiles']
})
So the nodes are created and their relationships too.
Now I want to set labels to the nodes relateds. How can I do this?
All the nodes you created already have a Profile label. But the neo4j Browser does not show the labels since normally you want identifying information to display for each node. However, the Browser does allow you to specify a different color for each label.
See the documentation for how to do that.
i'm trying to solve a problem of the 1: many relationship display in neo4j. My dataset is as below
child,desc,type,parent
1,PGD,Exchange,0
2,MSE 1,MSE,1
3,MSE 2,MSE,1
4,MSE 3,MSE,1
5,MSE 4,MSE,1
6,BRAS 1,BRAS,2
6,BRAS 1,BRAS,3
7,BRAS 2,BRAS,4
7,BRAS 2,BRAS,5
10,NPE 1,NPE,6
11,NPE 2,NPE,7
12,OLT,OLT,10
12,OLT,OLT,11
13,FDC,FDC,12
14,FDP,FDP,13
15,Cust 1,Customer,14
16,Cust 2,Customer,14
17,Cust 3,Customer,14
LOAD CSV WITH HEADERS FROM 'file:///FTTH_sample.csv' AS line
CREATE(:ftthsample
{child_id:line.child,
desc:line.desc,
type:line.type,
parent_id:line.parent});
//Relations
match (child:ftthsample),(parent:ftthsample)
where child.child_id=parent.parent_id
create (child)-[:test]->(parent)
//Query:
MATCH (child)-[childrel:test*]-(elem)-[parentrel:test*]->(parent)
WHERE elem.desc='FDP'
RETURN child,childrel,elem,parentrel
It returns a display as below.
I want the duplicate nodes to be displayed as one. Newbie with Neo4J. Can anyone of the experts help please?
This seems like an error in your graph creation query. You have a few lines in your query specifying the same node multiple times, but with multiple parents:
6,BRAS 1,BRAS,2
6,BRAS 1,BRAS,3
I'm guessing you actually want this to be a single node, with parent relationships to nodes with the given parent ids, instead of two separate nodes.
Let's adjust your import query. Instead of using a CREATE on each line, we'll use MERGE, and just on the child_id, which seems to be your primary key (maybe consider just using id instead, as a node can have an id on its own, without having to consider the context of whether it's a parent or child). We can use the ON CREATE clause after MERGE to add in the remaining properties only if the MERGE resulted in node creation (instead of matching to an existing node.
That will ensure we only have one node created per child_id.
Rather than having to rematch the child, we can use the child node we just created, match on the parent, and create the relationship.
LOAD CSV WITH HEADERS FROM 'file:///FTTH_sample.csv' AS line
MERGE(child:ftthsample {child_id:line.child})
ON CREATE SET
child.desc = line.desc,
child.type = line.type
WITH child, line.parent as parentId
MATCH (parent:ftthsample)
WHERE parent.child_id = parentId
MERGE (child)-[:test]->(parent)
Note that we haven't added line.parent as a property. It's not needed, since we only use that to create relationships, and after the relationships are there, we won't need those again.
I have a graph in which I am keeping the degree of a node as a property called "degree" in the node.
What I need is when I create an edge between two nodes, I need to increment the degree of the two nodes.
For creating unique edges I am using "CREATE UNIQUE" for the edges. So if I need to increment the property "degree" of the corresponding nodes, I need to use "ON CREATE" and "ON MATCH" as it is for "MERGE".
But I can't use the ON CREATE and ON MATCH with CREATE UNIQUE. So whats the proper way of using ON CREATE and ON MATCH with CREATE UNIQUE?
This is the way I am trying:
MATCH (n1:PER {Node_Id:"X"}), (n2:PER {Node_Id:"Y"}) WHERE n1.Node_Id<>n2.Node_Id CREATE UNIQUE (n1)-[r:PER_PER {Doc_Id:"st_new", Event_Class:"EC_1", Event_Instance:"EI_1"}]-(n2) ON CREATE SET n1.degree = n1.degree + 1, n2.degree = n2.degree + 1
Not sure why you want to store the degree as a property. Neo4j has a getDegree() function on API level, see http://neo4j.com/docs/stable/javadocs/org/neo4j/graphdb/Node.html#getDegree(). Cypher is not yet using this everywhere possible but for some patterns it already does.
Nevertheless to answer your question: just use MERGE instead of CREATE UNIQUE for eventually establishing the relationship:
MATCH (n1:PER {Node_Id:"X"}), (n2:PER {Node_Id:"Y"})
WHERE n1.Node_Id<>n2.Node_Id
MERGE (n1)-[r:PER_PER {Doc_Id:"st_new", Event_Class:"EC_1", Event_Instance:"EI_1"}]-(n2)
ON CREATE SET n1.degree = n1.degree + 1, n2.degree = n2.degree + 1
If you do have a good reason to store node degrees as a property, please have a look at one of our modules called RelCount, which has been build exactly for what you need to do. It is described in detail in my thesis.
However, as Stefan points out, have a go with getDegree() first and only if that isn't fast enough, or you need to get degree based on some relationship property values as well, use RelCount.
I am new to Neo4j. I have customer and product data into Neo4j. While loading I have not established any relationship among them. Now I want to establish relation among them like:
create (Customer1)-[:bought]->(Item1),(Customer1)-[:bought]->(Item2);
After I execute this statement it says Relationship established but as and when I try to access it like:
start n=node(*) match (n)-[:bought]->(items) where n.NodeName! = "Customer1" return items;
it says 0 rows. I think if it successfully establishes relationship it should give me 2 items, Item1 & Item2.
Any idea?
Apparently, you didn't set NodeName for your Customer1 node in your creation query. Try to modify it like this:
create (Customer1 { NodeName:'Customer1' }), (Item1 { NodeName:'Item1' }), (Item2 { NodeName:'Item2' }), (Customer1)-[:bought]->(Item1), (Customer1)-[:bought]->(Item2);
Then your second query should return 2 rows as you expected.
Update:
Ok, I didn't understand the question correctly. So, you want to establish a relationship between already existing nodes. Then try this:
start Customer1=node:node_auto_index(NodeName='Customer1'), Item1=node:node_auto_index(NodeName='Item1'), Item2=node:node_auto_index(NodeName='Item2')
create (Customer1)-[:bought]->(Item1),(Customer1)-[:bought]->(Item2);