I have been using cypher and neo4j for a while now, and I keep running into a similar problem again and again.
I would like to be able to add a "temporary" property to a node thats exists only in the returned data and is not persisted to the Neo4j database.
For example the current problem I am working on is given an N-ary tree structure in the graph database, I would like to return the children of a specific node, and an informational boolean letting me know weather those children have children.
The query to get this information is simple enough:
MATCH (parent:Item { guid: "Identifier here" })-[:HASCHILD]->(child:Item)
OPTIONAL MATCH (child)-[:HASCHILD]->(grandchild:Item)
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS has_children
Now I have the parent, child and a boolean letting me know weather there are further children.
What I would like to be able to do next is set the has_children boolean as a property on the child nodes, but just for returning the query, I don't need the property persisted.
I know there is are some solutions to get what I am looking for but none of them are specifically what I am looking for.
1) I could create a temporary node: (Continued from above query)
...
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS haschildren,
{
childkey1: child.childkey1,
childkey2: child.childkey2,
...
has_children: haschildren
} AS tempnode
RETURN parent, tempnode
This solution is not great, you have to know the exact node type and all the properties of the node you are dealing with, it will not work in the general case.
2) I could SET and REMOVE the boolean, temporarily persisting it to the database (as described in Neo4J create temp variable within Cypher).
This is not great as it will cause multiple db writes (for add and remove). Also, it is not as dynamic as option 1 as it would only be able to handle simple types. (Option 1 can handle more complex cases, like adding a collection of nodes instead of a simple boolean).
As far as I know, these are the only options when it comes to temporary return data. I'm wondering am I missing any thing? Is it possible to make this more simple or dynamic?
Something along the lines of
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS haschildren,
TEMPSET child.has_children = haschildren
Please note that I have simplified the examples given a little. I have run into this issue multiple times in different contexts in neo4j. Most times I either go with option 1, or build the correct structure by post-processing on the application side once the query returns.
Is there a better way?
You can try returning a map projection. Take a look in this example:
// Creating a sample node
CREATE (:Person {name:'Jon', id: 1})
Returning the projection with a extra boolean:
MATCH (p:Person {id:1})
WITH p, true AS has_children
RETURN p{.*, has_children:has_children}
The result:
╒═════════════════════════════════════════╕
│"p" │
╞═════════════════════════════════════════╡
│{"id":1,"name":"Jon","has_children":true}│
└─────────────────────────────────────────┘
The above query is returning all properties of p
node with an extra boolean.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With