Neo4j index not working without the Using keyword - neo4j

If I execute this query
match (p:Person),(c:Customer) using index p:Person(BusinessEntityID) where p.BusinessEntityID = c.CustomerID return p
the response is very quick.
If I remove the using keyword and execute this.
match (p:Person),(c:Customer) where p.BusinessEntityID = c.CustomerID return p
, the query takes forever to return result. I have about 50,000 nodes.
Also, the .Net client does not implement Using Index and I am basically stuck.
Could you please help as to how I can speed up the query.
note: I have indexes created on both BusinessEntityID and CustomerID on labels :Person and :Customer respectively.

perhaps you should create a relationship between the two, not doing a manual join on a property?
Then, please change it to this:
match (c:Customer)
match (p:Person)
where p.BusinessEntityID = c.CustomerID
return p

Related

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

Cypher query and Ruby on Rails

I have a Cypher query like this:
start n=node(*) match n-[:has_comments]->(m) return n,m;
which runs ok.
How can I run this from RoR?
When using Postgres and ActiveModel, in the controller I was able to do use something like this.
#query = "SELECT * FROM <table> WHERE <condition>;"
#result = <ClassName>.connection.execute(#query)
And after that I processed #result any way I wanted.
You can use Neo4j::Session.current.query to build general Cypher queries. Don't use START n=node anymore, that syntax isn't valid in future versions, so you should use MATCH (n) WHERE ID(n) = instead.
query = "MATCH (n)-[:has_comments]->(m) WHERE ID(n) = #{id} RETURN n, m"
result = Neo4j::Session.current.query(query).to_a
That'll give you an array of structs, with your results accessible by calling the n and m methods, respectively. I don't suggest you do it this way at all. As an alternative, you can do this:
result = Neo4j::Session.current.query.match("(n)-[:has_comments]->(m)").where("ID(n) = {id}").params(id: id).return(:n, :m)
You'll access the data the same way: n and m methods.
I don't recommend you do that, either. You're using Rails and ActiveNode, so you should have models and be able to do n_node.as(:n).comments(:m).pluck(:n, :m).

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

cypher query to traverse a graph

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

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