neo4j: how to query subgraph - neo4j

I want to select a subgraph(S) from my neo4j database and use another query on S to find if two given nodes are connected. Is there a way to write a query in neo4j ? I'm using node.js and Cypher.
EDIT:
I'm doing something similar to this, for example:
Match (u:User)-[:adds]->(y:Paper)-[:consistsOf]->(e:L2)-[]->(m:L3)
where u.username = 'test'
MATCH p=(m:L3)-[r:gives*1..4]->(n:L3)
...
Thanks

In your example, you could use the WITH clause to connect the 2 MATCH statements, like this (cleaned up a little):
MATCH (u:User {username:'test'})-[:adds]->(y:Paper)-[:consistsOf]->(e:L2)-->(m:L3)
WITH m
MATCH p=(m)-[r:gives*1..4]->(n:L3)
...
The WITH clause is like RETURN, except that its purpose is to pass value(s) from one query to the next. In this case, only 'm' is being passed, and so the second MATCH will not be aware of 'u', 'y', or 'e'.

Related

WHERE condition in neo4j | Filtering by relationship property

How does the where condition in neo4j works ?
I have simple data set with following relationship =>
Client -[CONTAINS {created:"yesterday or today"}]-> Transaction -[INCLUDES]-> Item
I would like to filter above to get the items for a transaction which were created yesterday, and I use the following query -
Match
(c:Client) -[r:CONTAINS]-> (t:Transaction),
(t) -[:INCLUDES]-> (i:Item)
where r.created="yesterday"
return c,t,i
But it still returns the dataset without filtering. What is wrong ? And how does the filtering works in neo4j for multiple MATCH statements say when I want to run my query on filetered dataset from previous steps?
Thank you very much in advance.
Your query seems fine to me. However, there are 2 things I would like to point out here:
In this case, the WHERE clause can be removed and use match by property instead.
The MATCH clause can be combined.
So, the query would be:
MATCH (c:Client) -[r:CONTAINS {created: "yesterday"}]-> (t:Transaction) -[:INCLUDES]-> (i:Item)
RETURN c, t, i
Regarding your second question, when you want to run another query on the filtered dataset from the previous step, use WITH command. Instead of returning the result, WITH will pipe your result to the next query.
For example, with your query, we can do something like this to order the result by client name and return only the client:
MATCH (c:Client) -[r:CONTAINS {created: "yesterday"}]-> (t:Transaction) -[:INCLUDES]-> (i:Item)
WITH c, t, i
ODERBY c.name DESC
RETURN c
There does not seem to be anything wrong with the cypher statement.
Applying subsequent MATCH statements can be done with the WITH clause, it's well documented here : https://neo4j.com/docs/cypher-manual/current/clauses/with/

Neo4j Cypher remove duplicates from simple query that contains ordering

I'm very new to Neo4J and I can't get this simple query work.
The data I have looks like this:
(a)-[:likes]->(b)
(a)-[:likes]->(c)
Now I'd like to extract a list with everyone who likes someone else.
Tried
match (u)-[:likes]->(p) return u order by p.id desc;
This gives me a duplicate of (a).
I tried using distinct:
match (u)-[:likes]->(p) return distinct u order by p.id desc;
This gives me 'variable p undefined'.
I know that if I drop the ordering, distinct works and gives me (a) once.
But how can I work with distinct and order by in the same time?
Consider why your query isn't working:
Without the distinct, you have rows with each pairing of u and p. When you use DISTINCT, how is it supposed to order when there are multiple lines for the same u, matching to multiple p's? That's an impossible task.
If you change it to order by u.id instead, then it works just fine.
I do encourage you to use labels, by the way, to restrict your query only to relevant nodes. You can also rework your query to prevent it from emitting duplicates and avoid the need for DISTINCT completely.
If we assume the nodes you're interested in are labeled with :Person, your query might be:
MATCH (p:Person)
WHERE EXISTS( (p)-[:likes]-() )
RETURN p ORDER BY p.id DESC

Aggregate over a list of matching nodes

I have a Cypher query which I'd like to expand to be summed up over a list of matching nodes.
My query looks like this:
MATCH (u:User {name: {input} })-[r:USES]-(t) RETURN SUM(t.weight)
This matches one User node, and I'd like to adjust it to match a list of User nodes and then perform the aggregation.
My current implementation just calls the query in a loop and performs the aggregation outside of Cypher. This results in slightly inaccurate results and a lot of API calls.
Is there a way to evaluate the Cypher query against a list of elements (strings in my case)?
I'm using Neo4j 2.1 or 2.2.
Cheers
You can use the IN operator and pass in an array of usernames:
MATCH (u:User)-[r:USES]-(t)
WHERE u.name in ['John','Jim','Jack']
RETURN u.name, SUM(t.weight)
Instead of the array here you can use an parameter holding and array value as well:
MATCH (u:User)-[r:USES]-(t)
WHERE u.name in {userNames}
RETURN u.name, SUM(t.weight)
userNames = ['John','Jim','Jack']

Neo4j Cypher: control order of MATCH based on input array?

I'm writing a query that iterates over some set of nodes:
MATCH (foo:Bar)
WHERE foo.id IN {ids}
Is there any way for me to specify/require/ensure that the matched nodes be in the same order as the input ids array?
As an analogy, with Neo4j 1.x, this was the behavior with native ID lookups:
START foo=node({ids})
For trivial cases, I can always re-order the results on the client myself. In this particular case, my query does some additional processing, and I want to make sure the nodes get processed in the right order.
Here's a console example to experiment with:
http://console.neo4j.org/r/l5oouj
Thanks!
UNWIND to the rescue!
UNWIND {ids} AS id
MATCH (foo:Bar {id: id})
http://console.neo4j.org/r/vit7c8

What is a better way of phrasing this Neo4J Cypher 2 query?

I have a query that takes too long to execute:
MATCH (s:Person{id:"103"}), s-[rel]-a WITH rel, s
MATCH c1-[:friend]->s<-[:friend]-c2, c1-[fol:follows]->c2
RETURN DISTINCT c1,c2;
However, when I split it in two:
MATCH (s:Person{id:"103"}), s-[rel]-a
RETURN rel, s;
and
MATCH (s:Person{id:"103"}),
c1-[:friend]->s<-[:friend]-c2, c1-[fol:follows]->c2
RETURN DISTINCT c1,c2;
they are much faster.
Why is it that passing rel and s to the next query makes it so much slower?
(I'm asking because that sample query is only a part of a bigger one and I pass on rel and s with the WITH instead of RETURN to the next part of the query)
Thank you
The first cycles for each node and relation found in the first MATCH:
MATCH (s:Person{id:"103"}), s-[rel]-a WITH rel, s
One row for each relation involving that node. I would use the third query, since rel is never used.
Maybe you try to "profile" the query in Neo4J console, it will give you some clues of how the query actually executed in server.
btw, why would you need to pass the on the "rel" since it never been used

Resources