完整路径的Neo4j查询

完整路径的Neo4j查询,neo4j,path,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`)-[:`

我有以下结构

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`)

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


我想提交两个或两个以上的单词,并找到一个路径,其中包括所有提交的单词和所有感兴趣的句子

不幸的是,这不是一个非常好的方法,它基本上归结为收集: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:句子)时(word in words…
表示
s
的初始匹配应该来自
words
集合中第一个
w
的匹配,因此它从所有开始:首先是句子节点,这是一个主要的性能影响

因此,为了解决这个问题,我们必须显式地匹配
单词集合中的第一个,然后使用
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
编辑:


添加了一个优化,以根据传入的:关联的\u到关系的程度对
w
节点进行排序(这是对极少数节点的程度查找),因为这意味着:句子节点的初始匹配是从其余单词中筛选关系之前可能的最小起始集。

我刚刚想起一种可能更有效的替代方法。将此查询中的配置文件与其他查询中的配置文件进行比较,看看它是否更适合您

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

作为替代,您可以考虑使用(也称为“遗留索引”)而不是使用<代码> Word < /COD>节点和<代码>关联到关系。手动索引支持使用“

”的“全文检索”搜索。 有很多方法可以帮助你

下面是一个可能适用于您的示例。在此示例中,我假设不区分大小写的比较是可以的,您保留
句子
节点(及其
文本
属性),并且希望自动将所有
句子
节点的
文本
属性添加到手动索引中

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

    dbms.security.procedures.unrestricted=apoc.*
    
  • 执行此密码以初始化名为“WordIndex”的手动索引,该索引包含来自所有现有
    语句
    节点的
    文本,并从该点开始启用自动索引:

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


  • 谢谢。我将从这个兔子洞开始。我将python和cypher混合在一起,所以也许我可以将上面的内容分解为几个较小的查询
    WITH REDUCE(s = $words[0], x IN $words[1..] | s + ' AND ' + x) AS q
    CALL apoc.index.search('WordIndex', q) YIELD node
    RETURN node;