cypher query to traverse a graph - neo4j

I am using last.fm dataset and imported it in neo4j 2.0.1. Now i want to traverse the graph so that I can get similar result which, I am getting by executing following MySQL query:
SELECT * from music.logs, music.features, music.nodespart2
WHERE logs.song="1000001"
AND logs.song=features.scrobble
AND fetures.mbid=nodespart2.name;
In neo4j I want to execute similar query,
starting from a particular index lets say 1000001->logs->features...
Any help would be appreciated.

I am not pretty sure about the graph model yet and what propertiess are you storing in the nodes and on relationship. But from the links you shared I think below query should work..
MATCH (a)-[:LOGS]->(b)-[:FEATURES]->(c) where a.type="listener"
and b.type="scrobble"
and c.type="track" and b.name = "100001" return *
This will give all listeners and tracks related to a particular scrobble with name 1000001
EDIT after comment
MATCH (b)-[:FEATURES]->(c) where b.type="scrobble" and c.type="track"
and b.name = "100001" return c.title
I would recommend to reimport your dataset with Labels. More info on labels: here. It will save the effort of checking type again and again and will enable you to incorporate it in the match pattern itself; also its more efficient.
EDIT after labels were added
Query1:
MATCH (a:listener)-[:LOGS]->(b:scrobble)-[:FEATURES]->(c:track)
where b.name = "100001" return *
Query2:
MATCH (b:scrobble)-[:FEATURES]->(c:track) where b.name = "100001" return c.title

Related

How to show relationships in an optional manner in neo4j?

I have multiple nodes and relationships in neo4j, certain nodes have relationship depth as 4, while certain have 2. I'm using neo4j's HTTP API to get the data in graph format
Sample query:
MATCH p= (n:datasource{resource_key:'ABCD'})-[:is_dataset_of]-(c:dataset)-[q]-(v:dataset_columns)-[s]-(b:component)-[w]-(e:dashboard) return p
If i use this query then i can get output if this exact relationship is present but I also want to get the output if the 2nd relationship is not available, Any pointers on how to achieve this?
Here is one way:
MATCH p = (:person1 {hobby: 'gamer'})-[:knows]-(:person2)
RETURN p
UNION ALL
MATCH p = (:person1 {hobby: 'gamer'})-[:knows]-(:person2)--(:person3)
RETURN p
The UNION clause combines the results of 2 queries. And the ALL option tells UNION to not bother to remove duplicate results (since the 2 subqueries will never produce the same paths).
If you really want the path to be returned, you can do something along these lines, using apoc (https://neo4j-contrib.github.io/neo4j-apoc-procedures/3.4/nodes-relationships/path-functions/)
MATCH requiredPath=(n)-[r]->(m)
OPTIONAL MATCH optionalPath = (m)-[q]->(s)
RETURN apoc.path.combine(requiredPath,optionalPath) AS p

Cypher query with variable length path and constraints on labels + link properties

I'm a newbie in Cypher and Graph DB...I am trying to display a kind of tree from my DB, with a source node, and the downstream leaves. I would like to filter on only the leaves that have only certain labels and where all the relationships have a specific constraint on their properties.
Root is a Column1 and I want to arrive on a Column1 as well, but there can be some Column2 in the path
I wrote this:
MATCH p=(:Column1{name:'Root'})-[*1..7]-(:Column1)
WHERE
all(n IN nodes(p)
WHERE all(l in labels(n)
WHERE l IN ['Column1', 'Column2']
)
AND n.deleted='0'
)
AND all(r IN relationships(p)
WHERE r.deleted='0')
RETURN p
When launched in Neo4J browser, the resulting graph is wrong and includes some relationships where deleted='1'. However, if I export the CSV table and look for deleted='1' (or even just 1), there are no result.
So it seems like the query is correct, but somehow, the graphical display will show the relationships where deleted=1.
Is it a bug, is it the query?
I also tried
MATCH (:Column1{name:'Root'})-[*1..7{deleted:'0'}]-(t)
WHERE t:Column1 or t:Column2
RETURN *
but in my DB, it takes forever to complete, compared to the previous query.
Solved it!
I had to uncheck the "Connect Result nodes" check box in the config tab of the browser. Otherwise, it queries for all the relationships between the displayed node!
Try doing
MATCH (:Column1 {name: 'Root'})-[*1..7 {deleted: '0'}]-(t)
WHERE labels(t)[0] IN ['Column1', 'Column2']
RETURN *
Depending on the amount of nodes Column1 has, and how many Column1 exists in your db, I wouldn't recommend this approach without a LIMIT 50 or whatever limit you want. If you do
PROFILE
MATCH (:Column1 {name: 'Root'})-[*1..7 {deleted: '0'}]-(t)
WHERE labels(t)[0] IN ['Column1', 'Column2']
RETURN *
You'll see just how many db hits this makes which is really resource consuming.

How to show only the nodes connected to the ones selected using Cypher of Neo4J?

I want to see only the nodes labeled ':Context' that are connected to all (or the maximum) number of the nodes labeled ':Concept'.
I'm currently using a query:
match (c:Concept), (ctx:Context), (c)-[r]->(ctx) where (c.name = 'italy' or c.name = 'pick') return ctx,c;
This gives out the following result:
How would I remove all the unnecessary green nodes (they are the ones of the ':Context' type) and only leave those, which are connected both to "pick" and "italy" :Concept nodes?
I also want to be able to perform the same search for 3 nodes and more. Can't understand what's the best way to do that (with or without APOC).
This query below works:
match (c1:Concept{name:"italy"})-->(ctx:Context)<--(c2:Concept{name:"pick"}) return ctx;
but only for 2 items. What if I want to do the same for 3 or more?
this one is too slow:
match (c1:Concept{name:"italy"})-->(ctx:Context)<--(c2:Concept{name:"pick"})-->(ctx:Context)<--(c3:Concept{name:"novice"}) return ctx;
Thanks!
You can match as many branches as you want in additional matches like this
match (c1:Concept{name:"italy"})-->(ctx:Context)<--(c2:Concept{name:"pick"})
match (c3:Concept{name:"france"})-->(ctx)
return ctx;
Although, I would recommend using params as they are more reusable. So assuming you have the param 'list' that contains ["italy", france", "pick"]
MATCH (c:Concept)
WHERE c.name in $list
WITH COLLECT(c) as concepts
MATCH (ctx:Context)
WHERE ALL(c in concepts WHERE (c)-->(ctx))
RETURN ctx

How to load all related node without includeing them in cypher in noe4jclinet

I am building a Query for cypher using Neo4jClient base on User search term.
my question is how can i load all the related nodes to first node that i am searching for.
here is a code sample in neo4jclient :
q.Return(post => post.As<Post>()).OrderBy("post.creationDate");
which produce something like this in cypher but without the result part:
MATCH (post:Post)-[:HAS_MentionedUsers]->(assignee1307989068:User),(post:Post)-[:HAS_HashTags]-> (Hashtag1841024507:HashTag)
WHERE (assignee1307989068.UserName = "mhs")
OR (Hashtag1841024507.Value = "myTag")
I am searching for the post but i need all the related node to Post to be included in the result set.
Make sure to have indexes for :User(UserName) and :HashTag(Value)
You create a cross product here, not sure that you want this, probably a union is better
You can just expand the pattern to contain other relationships off :Post too.
MATCH (o)-[r]-(post:Post)-[:HAS_MentionedUsers]->(assignee1307989068:User),
WHERE (assignee1307989068.UserName = "mhs")
RETURN post,o,r
UNION
MATCH (o)-[r]-(post:Post)-[:HAS_HashTags]-> (Hashtag1841024507:HashTag)
WHERE (Hashtag1841024507.Value = "myTag")
RETURN post,o,r

Getting multiple relationship property returns from a single cypher call

I'm new to cypher, neo4j and graph databases in general. The data model I was given to work with is a tad confusing, but it looks like the nodes are just GUID placeholders with all the real "data" as properties on relationships to the nodes (which relates each node back to node zero).
Each node (which basically only has a guid) has a dozen relations with key/value pairs that are the actual data I need. (I'm guessing this was done for versioning?.. )
I need to be able to make a single cypher call to get properties off two (or more) relationships connected to the same node -- here is two calls that I'd like to make into one call;
start n = Node(*)
match n-[ar]->m
where has(ar.value) and has(ar.proptype) and ar.proptype = 'ccid'
return ar.value
and
start n = Node(*)
match n-[br]->m
where has(br.value) and has(br.proptype) and br.proptype = 'description'
return br.value
How do I go about doing this in a single cypher call?
EDIT - for clarification;
I want to get the results as a list of rows with a column for each value requested.
Something returned like;
n.id as Node, ar.value as CCID, br.value as Description
Correct me if I'm wrong, but I believe you can just do this:
start n = Node(*)
match n-[r]->m
where has(r.value) and has(r.proptype) and (r.proptype = 'ccid' or r.proptype = 'description')
return r.value
See here for more documentation on Cypher operations.
Based on your edits I'm guessing that you're actually looking to find cases where a node has both a ccid and a description? The question is vague, but I think this is what you're looking for.
start n = Node(*)
match n-[ar]->m, n-[br]->m
where (has(ar.value) and has(ar.proptype) and ar.proptype = 'ccid') and
(has(br.value) and has(br.prototype) and br.proptype = 'description')
return n.id as Node, ar.value as CCID, br.value as Description
You can match relationships from two sides:
start n = Node(*)
match m<-[br]-n-[ar]->m
where has(ar.value) and has(ar.proptype) and ar.proptype = 'ccid' and
has(br.value) and has(br.proptype) and br.proptype = 'description'
return ar.value, br.value

Resources