neo4j - cypher query to find nodes which properties match object parameter - neo4j

I'm looking for a query which can find all of the nodes which have properties that match a parameter which is an object. The properties of the node can be a superset (contain more properties than the filter)
e.g.
:param obj : { first : "first" }
CREATE (n:Test { first : "first", second : "second" });
CREATE (m:Test { first : "first" });
CREATE (f:Fail { first : "bad", second : "second" });
MATCH (c)
WHERE
PROPERTIES(c) = $obj
RETURN c;
n and m should be returned as they are matching on first : "first"

it is doable with apoc, basically by matching the obj with a submap of the properties, containing only the keys that are also present in obj
WITH { first : "first" } AS obj
MATCH (c)
WHERE apoc.map.submap(properties(c),keys(obj),[],false)= obj
RETURN c

Related

Using Cypher, how to return a node with only a subset of its properties

Say I've created a node in Neo4j:
CREATE (:Thing {a:'foo', b:'bar'})
I can write a query to get that node with all of its properties
MATCH (n:Thing {a:'foo'}) RETURN n
which returns
{
"a": "foo",
"b": "bar"
}
but is it possible to match a node and retrieve only a subset of its properties, so that for example, Neo4j would return a node with only
{
"b": "bar"
}
(Not looking for just the property, like you would get via RETURN n.b)
Yes, you can use map projections in Cypher, for eg :
MATCH (n:Thing {a:'foo'}) RETURN n{.a}
will return :
{a:"foo"}
More info in the documentation

Neo4j expected Collection<T> but was Map when creating multiple nodes

I am trying to create multiple nodes in Neo4j using Cypher by passing properties as parameters as part of an UNWIND function, but I keep receiving the error Type mismatch: expected Collection<T> but was Map.
This happens even when using the following example from the Neo4j documentation (link):
UNWIND {
props : [ {
name : "Andres",
position : "Developer"
}, {
name : "Michael",
position : "Developer"
} ]
} AS map
CREATE (n)
SET n = map
Can anyone point out what I am doing wrong here?
Note, the example above is not exactly as in the Neo4j documentation. Their example wraps the property names in double quotes, but this causes my instance of Neo4j to throw the errorInvalid input '"': expected whitespace...)
UNWIND is expecting a collection, not a map as you're currently passing in, try this instead (just remove the wrapping curly braces and prop top level field):
UNWIND [ {
name : "Andres",
position : "Developer"
}, {
name : "Michael",
position : "Developer"
} ] AS map
CREATE (n)
SET n = map
Chris's answer is of course the correct one, but here's why your solution doesn't work when you're following the documentation: you're not copying the documentation.
The documentation shows the use of a named parameter:
UNWIND { props } AS map
CREATE (n)
SET n = map
with props passed in the map of parameters, which would look like:
{
"props" : [ {
"name" : "Andres",
"position" : "Developer"
}, {
"name" : "Michael",
"position" : "Developer"
} ]
}
if you displayed the map as JSON. It means the {props} placeholder will be replaced by the value for the props key. Which is exactly what Chris did.
Here's what the Java code would look like:
GraphDatabaseService db = /* init */;
Map<String, Object> andres = new HashMap<>();
andres.put("name", "Andres");
andres.put("position", "Developer");
Map<String, Object> michael = new HashMap<>();
michael.put("name", "Michael");
michael.put("position", "Developer");
Map<String, Object> params = new HashMap<>();
params.put("props", Arrays.asList(andres, michael));
try (Transaction tx = db.beginTx()) {
db.execute("UNWIND {props} AS map CREATE (n) SET n = map", params);
tx.success();
}

How to search a node filtering by an array field using multiple values

I store some values inside an array of a node and I would like to filter it using more than a single value. How could I do that?
Here it is my node:
CREATE (t:Test { value:["a","b","c"] } );
CREATE (t:Test { value:["a","b","d"] } );
CREATE (t:Test { value:["a","b","x"] } );
CREATE (t:Test { value:["a","y","z"] } );
CREATE (t:Test { value:["a","f","k"] } );
I would like to create a query that retrieves only items that "a" and "b" are inside values column.
The query below is not working but is close to what I would like to do.
MATCH (c:Test) WHERE ["a", "b"] IN c.value RETURN c
I know that I could split it using two "IN" commands (example below) but I would to like to avoid creating dynamic queries on my system.
MATCH (c:Test)
WHERE ALL(x IN ["a","b"] WHERE x IN c.value)
RETURN c.value

Neo4J deep duplicated nodes

For the data (below), my query looks like that:
MATCH p = (ob:Obiect)<--(w:Word { value:'game' })-[*]-(x) RETURN {id: id(x), value: x.value}
CREATE (w0:Obiect { value : 'Obiect' })
CREATE (w1:Word { value:'game' })
CREATE (w2:Word { value:'unreal' })
CREATE (w3:Word { value:'a' })
CREATE (w4:Word { value:'b'})
CREATE (w5:Word { value:'c' })
CREATE (w6:Word { value:'d'})
CREATE (w1)-[:IS]->(w0)
CREATE (w2)-[:IS]->(w1)
CREATE (w3)-[:HAS]->(w2)
CREATE (w4)-[:HAS]->(w3)
CREATE (w5)-[:HAS]->(w4)
CREATE (w6)-[:HAS]->(w5)
CREATE (w6)-[:HAS]->(w3)
If the relation (value:d)-->(value:a) doesn't exist then it’s okay and my results looks like this:
id 4070 value unreal
id 4071 value a
id 4072 value b
id 4073 value c
id 4074 value d
but if the relation exists then i have duplicates nodes (below). The question is how to avoid this problem?
id 4063 value unreal
id 4064 value a
id 4065 value b
id 4066 value c
id 4067 value d
id 4064 value a
id 4067 value d
id 4066 value c
id 4065 value b
id 4064 value a
You can use the MERGE clause : http://docs.neo4j.org/chunked/stable/query-merge.html
MERGE (w3:Word { value:'a' })
MERGE (w4:Word { value:'b'})
MERGE(w3)-[:HAS]->(w4)
MERGE acts as "MATCH or CREATE" .
Be aware that MERGE will attempt to match the entire pattern, which can be confusing the first times, so I recommend you this helpful article from Graphaware : http://graphaware.com/neo4j/2014/07/31/cypher-merge-explained.html

Neo4j Create only if not present query

I am using json to create nodes in noe4j
I have written a small c++ prog to do so using curl and json
Now i have to create around 10000 nodes in neo4j with properties having name and value.
For that i am using props in json with the query as
{
"params" : {
"props" : {
[{name : "a", value : 1}, {name : "b", value : 2}......so on]
]
}
},
"query" : "CREATE (n:Router { props }) RETURN n"
}
the question is I just want to create that nodes with unique names. If a node is already present with the name as in json props I do not want to create it.
How to write a query for these types of request in neo4j
Change your query to the following:
{
"params" : {
"props" : {
[{name : "a", value : 1}, {name : "b", value : 2}......so on]
]
}
},
"query" : "FOREACH (router in {props} | MERGE (n:Router {name: router.name}) ON CREATE SET n = router)"
}
Basically it iterate the items in your list, check for name property if it exist and it case it save a new node

Resources