I am trying to create the nodes using Cypher with the counter - neo4j

I am trying to create the nodes using Cypher with the counter how can I do it? I did not find anything helpful in documentation is there anyone who came across this case?

I have node named User and I wanted to create a property named "counterId". This is how I generated a counter from 1 to x where x is the number of all Users.
//collect all users in a list
MATCH (n:User)
WITH collect(n) as n_list
//for each user, set the counterId to this counter i
FOREACH(i IN range(1, size(n_list)+1) | set (n_list[i-1]).counterId = i);

Related

Cypher find node in list structure without using FOREACH CASE WHEN

We have following structure where User is starting point and numbers in nodes specify their names.
I am struggling to create a query to get specific numbered child node e.g. 2 without using FOREACH CASE WHEN hack.
The thing is our desired node might be linked directly to LIST relationship or deeper in PREV relationship chain.
Could you help me with that, please?
To find the 1 node that is on a path of LIST and/or PREV relationships from the 0 node, do this:
MATCH (u:User)-[:LIST|PREV*]->(x)
WHERE u.name = 0 AND x.name = 1
RETURN u, x

How to set Incremented value in nodes of neo4j

I have a couple of nodes and I need to add a incremental value in all nodes of a particular label.
match wd= (w:MYNODE)
forEach(n IN nodes(wd)|
set n.incrementalId=??
);
currently I have tried for each to traverse on each node but unable to get index of the each loop
ps: I have also tried with but unable to increment ie ++ the current value.
This is a more succinct version of #InverseFalcon's first query (and resembles the form of the query in your question):
MATCH (w:MYNODE)
WITH COLLECT(w) as ws
FOREACH(i IN RANGE(0, SIZE(ws)-1) | SET (ws[i]).incrementalId = i);
If the nodes already exist, then you'll have to use a more awkward approach using collections and indexes:
MATCH (w:MYNODE)
WITH collect(w) as myNodes
UNWIND range(0, size(myNodes)-1) as index
WITH index, myNodes[index] as node
SET node.incrementalId = index
If the nodes don't already exist, and you want to create some number of them with incremental ids, then it's an easier task using the range() function to produce a list of indexes:
UNWIND range(1, 100) as id
CREATE (:MYNODE {id:id})

Create relationships in Neo4j

I have a graph with about 800k nodes and I want to create random relationships among them, using Cypher.
Examples like the following didn't work because the cartesian product is too big:
match (u),(p)
with u,p
create (u)-[:LINKS]->(p);
For example I want 1 relationship for each node (800k), or 10 relationships for each node (8M).
In short, I need a query Cypher in order to UNIFORMLY create relationships between nodes.
Does someone know the query to create relationships in this way?
So you want every node to have exactly x relationships? Try this in batches until no more relationships are updated:
MATCH (u),(p) WHERE size((u)-[:LINKS]->(p)) < {x}
WITH u,p LIMIT 10000 WHERE rand() < 0.2 // LIMIT to 10000 then sample
CREATE (u)-[:LINKS]->(p)
This should work (assuming your neo4j server has enough memory):
MATCH (n)
WITH COLLECT(n) AS ns, COUNT(n) AS len
FOREACH (i IN RANGE(1, {numLinks}) |
FOREACH (x IN ns |
FOREACH(y IN [ns[TOINT(RAND()*len)]] |
CREATE (x)-[:LINK]->(y) )));
This query collects all nodes, and uses nested loops to do the following {numLinks} times: create a LINK relationship between every node and a randomly chosen node.
The innermost FOREACH is used as a workaround for the current Cypher limitation that you cannot put an operation that returns a node inside a node pattern. To be specific, this is illegal: CREATE (x)-[:LINK]->(ns[TOINT(RAND()*len)]).

Neo4j / Cypher: aggregate using reduce

I'm trying to do some basic similarity search in a neo4j database. It looks something like this:
begin
create (_1:`Article` {`name`:"Bow", `weight`:"20"})
create (_2:`Article` {`name`:"Shield", `weight`:"30"})
create (_3:`Article` {`name`:"Knife", `weight`:"40"})
create (_4:`Article` {`name`:"Sword", `weight`:"50"})
create (_5:`Article` {`name`:"Helmet", `weight`:"15"})
create (_6:`Order` {`customer`:"Peter"})
create (_7:`Order` {`customer`:"Paul"})
create (_8:`Order` {`customer`:"Mary"})
create (_9:`Accessory` {`name`:"Arrow",`type`:"optional", `weight`:"2"})
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_1
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_2
create _6-[:`CONTAINS` {`timestamp`:"1413204480"}]->_3
create _7-[:`CONTAINS` {`timestamp`:"1413204480"}]->_1
create _7-[:`CONTAINS` {`timestamp`:"1413204480"}]->_4
create _8-[:`CONTAINS` {`timestamp`:"1413204480"}]->_5
create _9-[:`BELONGS_TO` {`timestamp`:"1413204480"}]->_1
;
commit
Pretty pointless database, I know. Sole reason for it is this post.
When a new order comes in, I need to find out, whether or not similar orders have already been placed. Similar means: existing or new customer and same products. The hard part is: I need the sum of the weight of all (directly or indirectly) contained nodes.
Here's what I have:
START n=node(*)
MATCH p1 = (a:Order)-[*]->n, p2 = (b:Order)-[*]->m
WHERE a<>b AND n.name = m.name
RETURN reduce (sum="", x in p2 | sum+x.weight) limit 25;
However, it seems that p2 is not the right thing to aggregate across. Cypher expects a collection and not a path.
Truly sorry for this newbie post, but rest assured: I am a very grateful newbie. Thanks!
rene
In your query, it looks like you are pretending that p2 is the path of you new order. I presume that in your actual query you will be binding b to a specific node. Also, your timestamps and weights should have numeric values (without the quotes).
This query will return the total weight of the "new" path. Is this what you wanted?
MATCH p1 =(a:Order)-[*]->n, p2 =(b:Order)-[*]->m
WHERE a<>b AND n.name = m.name
WITH p2, collect(m) AS ms
RETURN reduce(sum=0, x IN ms | sum+x.weight)
LIMIT 25;
By the way, START n=node(*) is superfluous. It is the same as using an unbound n.
See this console.

Reliable (auto)incrementing identifiers for all nodes/relationships in Neo4j

I'm looking for a way to generate unique identifiers for all my nodes/relationships in Neo4j, based on an incrementing counter (not big long uuids).
The internal ids maintained by the Neo4j engine are known not to be reliable as outside references.
A solution that comes close is the code proposed in this question, but it doesn't work when a single CREATE clause creates multiple new nodes:
// get unique id
MERGE (id:UniqueId{name:'Person'})
ON CREATE SET id.count = 1
ON MATCH SET id.count = id.count + 1
WITH id.count AS uid
// create a new node attached to every existing :something node
MATCH (n:something)
CREATE (:somethingRelated {id:uid}) -[:rel]-> (n)
When there are multiple (n:something), every newly created (:somethingRelated) will share the same id. Is there some way around this, using only Cypher?
Try this to allocate a block of ids:
// collect nodes to connect
MATCH (n:Crew) WITH collect(n) AS nodes
MERGE (id:UniqueId { name:'Person' })
// reserve id-range
SET id.count = coalesce(id.count,0)+ size(nodes)
WITH nodes, id.count - size(nodes) AS base
// for each index
UNWIND range(0,size(nodes)-1) AS idx
// get node, compute id
WITH nodes[idx] AS n, base +idx AS id
CREATE (:SomethingRelated { uid:id })-[:rel]->(n)
From my point of view it's not possible to do that in Cypher.
I suggest you to write Java Extension for that, because your approach with Cypher would not work in concurrent environment. You are not able to secure uniqueness.
Could you please tell us more about your use case and why you don't to use UUID? - https://github.com/graphaware/neo4j-uuid
Based on your comment below I suggest to create ID's in your application.

Resources