ganninu93
ganninu93

Reputation: 1601

Neo4j - Get node containing a list of children

I have a Document - [:Contains] -> Keyword relationship. I would like to obtain all the documents having a specified list of keywords. So far I managed to do this:

Match (d:document)-[:CONTAINS]->(k1:keyword {keyword:"key1"})
WITH d,k1
MATCH (d)-[CONTAINS]->(k2:keyword {keyword:"key2"})
return d, k1, k2

The above query returns all documents containing both "key1" and "key2" as keywords. The problem is that the query has to be modified depending on the number of keywords I am looking for. Is it possible to use a list as the search parameter and modify the list rather than the query itself?

Upvotes: 2

Views: 307

Answers (2)

ganninu93
ganninu93

Reputation: 1601

In addition to what @cybersam suggested, this solution returns only those documents which match ALL the keywords.

MATCH (d:document)-[:CONTAINS]->(k:keyword)
WITH d,k, ["key1", "key2"] AS input
WHERE k.keyword IN input 
WITH d, input, COUNT(k) AS cnt
WHERE cnt=size(input)
return d, cnt;

Upvotes: 0

cybersam
cybersam

Reputation: 66967

[UPDATED]

A query like this should work:

MATCH (d:document)-[:CONTAINS]->(k:keyword)
WHERE k.keyword IN {keywords}
RETURN d, COUNT(k) AS cnt
ORDER BY cnt DESC;

In this query, keywords is assumed to be a collection of keyword strings passed as a parameter. I also assumed that CONTAINS is a relationship type, hence I added the : prefix.

For better performance, you can create an index on the keyword property of the keyword node label. (In practice, you should probably give the label and the property different names...).

CREATE INDEX ON :keyword(keyword);

After this, you may have to alter the original query to cajole the Cypher planner into using the index:

MATCH (d:document)-[CONTAINS]->(k:keyword)
USING INDEX k:keyword(keyword)
WHERE k.keyword IN {keywords}
RETURN d, COUNT(k) AS cnt
ORDER BY cnt DESC;

Upvotes: 3

Related Questions