Neo4j Cypher:查找一组匹配节点之间的公共节点

时间:2017-01-04 21:15:17

标签: database graph neo4j cypher

与发布here

的问题非常相似

我有以下节点:文章和单词。每个单词都通过MENTIONED关系与文章相关联。

我需要查询所有具有常用单词的文章,其中常用单词列表是动态的。从客户的角度来看,我正在传回一个单词列表,并期待找到具有这些单词的文章的结果。

以下查询执行作业

WITH ["orange", "apple"] as words
MATCH (w:Word)<-[:MENTIONED]-(a:Article)-[:MENTIONED]->(w2:Word)
WHERE w.name IN words AND w2.name IN words
RETURN a, w, w2

但不适用于单词列表。如何处理任意数量的单词?有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

是。我能想到两种方法:

  1. 查找包含这些单词的某些子集的所有文章,然后仅返回所提及的单词数量是您在单词列表中提供的单词数量的文章。

  2. 获取给定单词列表的Word节点,然后获取文章中提及所有单词的文章。

  3. 以下是测试此内容的示例图表:

    MERGE (a1:Article {name:'a1'}), 
          (a2:Article {name:'a2'}), 
          (a3:Article {name:'a3'})
    MERGE (w1:Word{name:'orange'}), 
          (w2:Word{name:'apple'}), 
          (w3:Word{name:'pineapple'}), 
          (w4:Word{name:'banana'})
    MERGE (a1)-[:MENTIONED]->(w1), 
          (a1)-[:MENTIONED]->(w2), 
          (a1)-[:MENTIONED]->(w3), 
          (a1)-[:MENTIONED]->(w4),
          (a2)-[:MENTIONED]->(w1), 
          (a2)-[:MENTIONED]->(w4),
          (a3)-[:MENTIONED]->(w1), 
          (a3)-[:MENTIONED]->(w2),
          (a3)-[:MENTIONED]->(w3)
    

    方法1,将词汇表大小与文章中提到的词数进行比较,如下所示:

    WITH ["orange", "apple"] as words
    MATCH (word:Word)<-[:MENTIONED]-(article:Article)
    WHERE word.name IN words
    WITH words, article, COUNT(word) as wordCount
    WHERE wordCount = SIZE(words)
    RETURN article
    

    只有在文章和提到的单词之间只有一个:MENTIONED关系时,这才有效,无论该单词被提及多少次。

    方法2在集合上使用ALL():单词以确保我们匹配所有提及所有单词的文章:

    WITH ["orange", "apple"] as words
    MATCH (word:Word) 
    WHERE word.name in words
    WITH COLLECT(word) as words
    MATCH (article:Article)
    WHERE ALL (word in words WHERE (word)<-[:MENTIONED]-(article))
    RETURN article
    

    您可以尝试使用PROFILE来确定哪种方法最适合您的数据集。