简体   繁体   中英

Neo4j - Iterate for common nodes for a given list of nodes

I have no idea of iterating on list in neo4j. Please some one suggest the idea for the below problem.

Example: I have some nodes in the graph. Then, I will give few(always varying, this is the user input) keywords to search for nodes which are common to this words. In my graph each word is a node.

Ex: Input: [Best sports car]
output: connected nodes for Best are [samsung,porshe,ambassdor,protein,puma]
        connected nodes for sports are [cricket,racing,rugby,puma,porshe]
        connected nodes for car are [porshe,ambassdor,benz,audi]
Common nodes to all words are : [porshe]
Result is : porshe

I don't have any idea of iterating each word and storing the match results. Please some one suggest any idea.

In order to test the following working query, I'll make some assumptions :

  • The words nodes have the label :Word and the name property.
  • The porsche, puma, etc.. nodes have the label :Item and a name property .
  • Item nodes have an outgoing CONNECT relationships to Word nodes

Which will give the following graph :

在此处输入图片说明

The query is the following (in order to simulate the given words as parameters, I added a WITH containing the words list in the beginning of the query)

WITH ["car","best","sports"] as words
MATCH (n:Word)<-[:CONNECT]-(i:Item) 
WHERE n.name IN words
WITH i, count(*) as c, words
WHERE c = size(words)
RETURN i

And will return only the porsche Item node.

Logic explanation

The logic of the query, is that if a node matches all given words, there will be 3 patterns to it found in the first MATCH , so the count(*) will have a value of 3 here for the porsche node. This value is compared to the size of the words list.

More explanations

In the WITH statement, there is two expressions : i and count(*) .

i is not an aggregate function, so it will act as a grouping key. count(*) is an aggregate function and will run on the i bucket, calculating the aggregate values.

For example, if you want to know how many words each Item is matching you can simply do :

WITH ["car","best","sports"] as words
MATCH (n:Word)<-[:CONNECT]-(i:Item) WHERE n.name IN words
RETURN i.name, count(*)

Which will return this :

在此处输入图片说明

You can see that porsche is matching 3 words, which is the size of the given words list, then you can simply compare the 3 from the count aggregation to this size .

In order to fully understand how aggregation works, you can refer to the manual : http://neo4j.com/docs/stable/query-aggregation.html

You can test the query here :

http://console.neo4j.org/r/e6bee0

If you pass the words as parameters, this will then be the corresponding query :

MATCH (n:Word)<-[:CONNECT]-(i:Item) 
WHERE n.name IN {words}
WITH i, count(*) as c
WHERE c = size({words})
RETURN i

assuming {words} is the name of the given query parameter

Is something like this what you are after?

Start with a collection of words form the requested search.

Match each word against the graph.

Collect the connected words in a list.

with ['Best', 'sports', 'car'] as word_coll
unwind word_coll as word
match (:Word {name: word})--(conn_word:Word)
return word,collect(conn_word)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM