Cypher 查询 return 不良结果

Cypher query return undesirable result

我需要获取文本并将它们保存到 Neo4j。之后,我将该文本的每个单词分开,并在它们之间创建一个 [:NEXT] 关系,指示另一个单词之后的单词,并创建一个 [:CONTAINS] 关系,指示该文本包含该单词。 最后,我尝试在文本中找到具有更多关系 [:NEXT] 但不是在整个数据库中的单词。仅在给定的文本中。

不幸的是,我只得到了整个数据库的总和。

查询是:

query = '''
        WITH split("%s"," ") as words 
        MERGE (p:Post {id: '%s', text: '%s'})
        WITH p, words
        UNWIND range(0,size(words)-2) as idx
        MERGE (w1:Word {name:words[idx]})
        MERGE (w2:Word {name:words[idx+1]})
        MERGE (w1)-[:NEXT]->(w2)
        MERGE (p)-[:CONTAINS]->(w2)
        MERGE (p)-[:CONTAINS]->(w1)
        WITH p
        MATCH (p)-[c:CONTAINS]->(w:Word)
        MATCH ()-[n1:NEXT]->(:Word {name: w.name})<-[:CONTAINS]-(p)
        MATCH (p)-[:CONTAINS]-(:Word {name: w.name})-[n2:NEXT]->()
        WITH COUNT(n1) + COUNT(n2)AS score, w.name AS word, p.text AS post, p.id AS _id
        RETURN post, word, score, _id;
        '''  %(text, id, text)

我只是找不到这里的问题。

谢谢!

嗯,您可能遇到了数据建模问题。

您在创建单词节点时正在使用 MERGE,因此如果该单词是从任何先前的文本查询中添加的,它将重复使用同一节点,因此您更常用的单词节点(a、the 和 I等) 可能会有许多 [:NEXT] 关系,这些关系将随着每个查询而继续增长。

这就是您的意思,还是您只询问数据库有关查询中仅给定文本中使用的词的问题?

编辑

问题是 :Word 节点的合并。这将匹配任何先前的 :Word 节点,该节点是从任何先前的查询创建的,并将与任何未来的查询匹配。合并 :Word 节点本身是不够的;要使您的单词仅对每个关联的 post 本地化,您必须同时合并 post 中单词的关系。

我们还可以清理用于匹配的模式来计算单词得分,因为我们只需要每个单词任何方向的 [:NEXT] 关系的数量。

    query = '''
    WITH split("%s"," ") as words 
    MERGE (p:Post {id: '%s', text: '%s'})
    WITH p, words
    UNWIND range(0,size(words)-2) as idx
    MERGE (p)-[:CONTAINS]->(w1:Word {name:words[idx]})
    MERGE (p)-[:CONTAINS]->(w2:Word {name:words[idx+1]})
    MERGE (w1)-[:NEXT]->(w2)
    WITH p
    MATCH (p)-[:CONTAINS]->(w:Word)
    WITH size( ()-[:NEXT]-(w) ) AS score, w.name AS word, p.text AS post, p.id AS _id
    RETURN post, word, score, _id;
    '''  %(text, id, text)

我的解决方案是:

query = '''
    WITH split("%s"," ") AS words 
    MERGE (p:Post {id: "%s", text:"%s"})
    WITH p, words 
    UNWIND range(0,size(words)-2) as idx
    MERGE (w1:Word {name:words[idx]})
    MERGE (w2:Word {name:words[idx+1]})
    MERGE (w1)-[n:NEXT]->(w2)
    ON MATCH SET n.count = n.count + 1
    ON CREATE SET n.count = 1
    MERGE (p)-[:CONTAINS]->(w2)
    MERGE (p)-[:CONTAINS]->(w1)
    '''  %(text, id, text)