Update properties of many nodes selected by ID - neo4j

This is a slightly different question from one answered here:
Update multiple nodes in a single query, each with different property / value pairs
The selected answer to that question presented a nifty query to update many nodes by their 'uuid':
UNWIND { data } AS d
MERGE (x {uuid: d.uuid})
SET x += d.props
My question is how would you accomplish this if you wanted to select by ID(x)? While most of my nodes do have a uuid property, my relationships do not and I need to update their properties as well.
Thanks!

You'll need to process your nodes and relationships separately. Relationships would process similar to this:
UNWIND { data } AS d
MATCH ()-[r]-()
WHERE id(r) = d.id
SET r += d.props
Node processing would be similar, just use MATCH (n) WHERE id(n) = d.id

Related

Cypher sorting by number of related nodes?

I'm learning Cypher and I created a "Criminal investigation" project on Neo4j.
I'm trying to run a query that outputs each Person that has two children (Person) and both of the children must have committed a crime. To achieve this, I was testing some queries with a Person (p) called p.name = "Lillian" so I know this person has two children but just one of them has committed a crime.
In order to make this I execute this query (return something if Lillian has two sons that committed crimes or return nothing contrarily:
match (p:Person)-[r:FAMILY_REL]->(s:Person)
where p.name = "Lillian"
and size((p)-[:FAMILY_REL]->()-[:PARTY_TO]->(:Crime))=2 and size((p)-[:FAMILY_REL]->()) = 2
return p, s
As I already knew Lillian has only one son who committed a crime, the query should have not returned anything but it returned both of their children.
I'm guessing the wrong part of the query is here:
where /*...*/ and size((p)-[:FAMILY_REL]->()-[:PARTY_TO]->(:Crime))=2
I think this is counting just the number of children instead the number of children who have committed crimes.
What would be the correct way to do this?
Give this a try:
MATCH (p:Person)
WHERE p.name = "Lillian" AND size((p)-[:FAMILY_REL]->()) = 2
WITH p, [(p)-[:FAMILY_REL]->(child) WHERE (child)-[:PARTY_TO]->(:Crime) | child] as childCriminals
WHERE size(childCriminals) = 2
UNWIND childCriminals as s
RETURN p, s
Note that this will only work if Lillian has exactly two children, and both have been party to a crime.
As for why your query wasn't working, it's likely that one of the children was party to two crimes, that would produce results.

neo4j query to match nodes based on the number of properties

I have a node with 8 properties and another node with only property under a common label. How can i match / query / display the nodes which has only property.
In other words, how can i match nodes which doesn't have more than 1 property.
You may want something like:
MATCH (n)
WHERE size(keys(n)) = 1
RETURN n
However note that this is a graph-wide query, and likely to be expensive. Confining the query to a label may help a little.
As Michael Hunger mentioned
MATCH (n) WHERE NOT EXISTS(n.foo) RETURN n
Duplicate of the question : Find neo4j nodes where property is not set

Neo4j cypher query on relationship property return relative results

I have nodes A and B and a relationship R from A to B. R has a property date_created. Is it possible to construct a Neo4j query that matches a specific A and returns the related (through R) B nodes with, say, the 10 highest values of date_created?
I think it would be straightforward if I wanted to return the B nodes that had a date_created property on R of greater than some specific date, but not sure if I can do the kind of relative query I want to do?
Thanks,
Paul
You aren't listing any labels, so I'll assume that you have a 'Object' label:
MATCH (a:Object)-[:r]->(b:Object)
WHERE a.some_property = {some_value}
RETURN b
ORDER BY r.date_created DESC
LIMIT 10

neo4j - match nodes and add relationships to them

how do i add relationships to nodes returned by a cypher query?
I have written a query that returns me all the person nodes who have the same surname who live at the same address. I now want to add a relationship between these person nodes to indicate they are the same person. The query below returns me 3 person nodes and I want to add a relationship from the first node (returned by the ORDER BY) to the other 2.
MATCH (a:Address) <-[LIVES_AT]-(p:Person)
WITH a as addnode, p.surname as psurname, COUNT(p.name_urn) as c
WHERE c > 1
MATCH (a2:Address{address_urn:addnode.address_urn})<-[LIVES_AT]- (p2:Person{surname:psurname})
WITH p2 as p2node
ORDER BY CASE
WHEN p2node.master_record = 'Y'
THEN
1
ELSE
2
END
WITH collect(p2node) as colp2node
RETURN colp2node
Hope this makes sense? Please advise if there is a better way of doing this.
Something like this should work for you:
MATCH (a:Address)<-[LIVES_AT]-(p:Person)
WITH a, p.surname AS psurname, COUNT(p.name_urn) AS c
WHERE c > 1
MATCH (a2:Address { address_urn:a.address_urn })<-[LIVES_AT]-(p2:Person { surname:psurname })
WITH p2
ORDER BY CASE WHEN p2.master_record = 'Y' THEN 1 ELSE 2 END
WITH collect(p2) AS colp2
WITH colp2[0] AS master, colp2[1..] AS others
UNWIND others AS other
MERGE (master)-[:HAS_ALIAS]->(other);
I use MERGE to avoid duplicate relationships.
By the way, just because two people have the same surname and live at the same address, that does not normally mean they are the same person. I hope you are sure that what you are doing is appropriate.

Keep track of Changes in Neo4j - Achieve functionality like a "flag" variable in standard programming

Initial setup of the sample database is provided link to console
There are various cases and within each case, there are performers(with properties id and name). This is the continuation of problems defined problem statement and solution to unique node creation
The solution in the second link is (credits to Christophe Willemsen
)
MATCH (n:Performer)
WITH collect(DISTINCT (n.name)) AS names
UNWIND names as name
MERGE (nn:NewUniqueNode {name:name})
WITH names
MATCH (c:Case)
MATCH (p1)-[r:RELATES_TO]->(p2)<-[:RELATES]-(c)-[:RELATES]->(p1)
WITH r
ORDER BY r.length
MATCH (nn1:NewUniqueNode {name:startNode(r).name})
MATCH (nn2:NewUniqueNode {name:endNode(r).name})
MERGE (nn1)-[rf:FINAL_RESULT]->(nn2)
SET rf.strength = CASE WHEN rf.strength IS NULL THEN r.value ELSE rf.strength + r.value END
This solution achieved what was asked for.
But I need to achieve something like this.
foreach (Case.id in the database)
{
foreach(distinct value of r.Length)
{
//update value property of node normal
normal.value=normal.value+0.5^(r.Length-2)
//create new nodes and add the result as their relationship or merge it to existing one
MATCH (nn1:NewUniqueNode {name:startNode(r).name})
MATCH (nn2:NewUniqueNode {name:endNode(r).name})
MERGE (nn1)-[rf:FINAL_RESULT]->(nn2)
//
rf.strength=rf.strength + r.value*0.5^(r.Length-2);
}
}
The problem is to track the change in the case and then the r.Length property. How can it be achieved in Cypher?
I will not redo the last part, where setting strengths.
One thing though, in your console link, there is only one Normal node, so why do you need to iterate over each case, you can just match distinct relationships lengths.
By the way for the first part :
MATCH (n:Case)
MATCH (n)-[:RELATES]->()-[r:RELATES_TO]->()<-[:RELATES]-(n)
WITH collect(DISTINCT (r.length)) AS lengths
MATCH (normal:Normal)
UNWIND lengths AS l
SET normal.value = normal.value +(0.5^l)
RETURN normal.value
Explanations :
Match the cases
Foreach case, match the RELATES_TO relationships of Performers for that Case
collect distinct lengths
Match the Normal node, iterate the the distinct lengths collection and setting the proper value on the normal node

Resources