Neo4j查询完整路径

时间:2017-05-23 05:38:38

标签: neo4j path

我有以下结构。

CREATE 
(`0` :Sentence {`{text`:'This is a sentence'}}) ,
(`1` :Word {`{ text`:'This' }}) ,
(`2` :Word {`{text`:'is'}}) ,
(`3` :Sentence {`{'text'`:'Sam is a dog'}}) ,
(`0`)-[:`RELATED_TO`]->(`1`),
(`0`)-[:`RELATED_TO`]->(`2`),
(`3`)-[:`RELATED_TO`]->(`2`)

schema example

所以我的问题是这个。我有一堆句子,我已经分解成单词对象。这些单词对象都是唯一的,因此会指向不同的句子。如果我搜索一个单词,很容易找出与单词相关的所有句子。如何构造查询以找出两个单词而不是一个单词的相同信息。

我想提交两个或更多单词,并找到一条路径,其中包含所有提交的单词,并将所有感兴趣的句子提取出来。

3 个答案:

答案 0 :(得分:1)

我只记得一种可能更好的替代方法。将此查询的PROFILE与其他查询的配置文件进行比较,看看它是否适合您。

WITH {myListOfWords} as wordList
WITH wordList, size(wordList) as wordCnt
MATCH (s)-[:RELATED_TO]->(w:Word) 
WHERE w.text in wordList
WITH s, wordCnt, count(DISTINCT w) as cnt
WHERE wordCnt = cnt
RETURN s

答案 1 :(得分:0)

不幸的是,这不是一个非常漂亮的方法,它主要归结为收集:Word节点并使用ALL()谓词来确保所需的模式对于集合的所有元素都适用。

MATCH (w:Word) 
WHERE w.text in {myListOfWords}
WITH collect(w) as words
MATCH (s:Sentence)
WHERE ALL(word in words WHERE (s)-[:RELATED_TO]->(word))
RETURN s

让这个丑陋的原因是,当你说MATCH (s:Sentence) WHERE ALL(word in words ... s的初始匹配应来自第一个匹配时,规划师现在还不够智能推断w集合中的words,因此它从所有节点开始:首先是句子节点,这是主要的性能影响。

为了解决这个问题,我们必须从words集合中的第一个明确匹配,然后使用WHERE ALL()进行剩余。

MATCH (w:Word) 
WHERE w.text in {myListOfWords}
WITH w, size(()-[:RELATED_TO]->(w)) as rels
WITH w ORDER BY rels ASC
WITH collect(w) as words
WITH head(words) as head, tail(words) as words
MATCH (s)-[:RELATED_TO]->(head)
WHERE ALL(word in words WHERE (s)-[:RELATED_TO]->(word))
RETURN s

编辑:

添加了一个优化,以根据传入的程度对w个节点进行排序:RELATED_TO关系(这是极少数节点上的度数查找),因为这意味着与您的:Sentence节点的初始匹配是在从其他单词过滤关系之前,可能的最小起始集。

答案 2 :(得分:0)

作为替代方案,您可以考虑使用manual indexing(也称为“遗留索引”),而不是使用Word节点和RELATED_TO关系。手动索引使用lucene支持“全文”搜索。

有很多apoc procedures可以帮助您解决此问题。

这是一个可能适合您的示例。在此示例中,我假设不区分大小写的比较正常,您保留Sentence个节点(及其text属性),并且您希望自动添加所有text属性Sentence 1}}节点到手动索引。

  1. 如果您使用的是neo4j 3.2+,则必须将此设置添加到neo4j.conf文件中,以便使一些昂贵的apoc.index程序(如apoc.index.addAllNodes)可用:

    dbms.security.procedures.unrestricted=apoc.*
    
  2. 执行此Cypher代码,使用所有现有text节点中的Sentence文本初始化名为“WordIndex”的手动索引,并启用从该点开始的自动索引:

    CALL apoc.index.addAllNodes('WordIndex', {Sentence: ['text']}, {autoUpdate: true})
    YIELD label, property, nodeCount
    RETURN *;
    
  3. 要查找(不区分大小写)包含集合中所有单词的Sentence节点(通过$words parameter传递),您将执行类似Cypher的语句下面的一个。 WITH子句为您构建lucene查询字符串(例如,“foo AND bar”)。警告:由于lucene的特殊布尔术语(如“AND”和“OR”)始终为大写,因此应确保传入的单词是小写的(或修改下面的WITH子句以使用TOLOWER() `功能根据需要)。

    WITH REDUCE(s = $words[0], x IN $words[1..] | s + ' AND ' + x) AS q
    CALL apoc.index.search('WordIndex', q) YIELD node
    RETURN node;