Cypher:嵌套大的WHERE / CONTAINS子句对性能有何影响?

时间:2018-08-01 17:29:23

标签: performance neo4j cypher query-optimization

我正在使用具有较大WHERE子句的查询:

WHERE (
        (n.val CONTAINS 'wrd1-1' AND n.val CONTAINS 'wrd1-2' AND n.val CONTAINS 'wrd1-3') OR
        (n.val CONTAINS 'wrd2-1' AND n.val CONTAINS 'wrd2-2' AND n.val CONTAINS 'wrd2-3') OR
        (n.val CONTAINS 'wrd3-1' AND n.val CONTAINS 'wrd3-2' AND n.val CONTAINS 'wrd3-3') OR
        .
        .
        .

        (n.val CONTAINS 'wrd20-1' AND n.val CONTAINS 'wrd20-2' AND n.val CONTAINS 'wrd20-3')
      )

n.val是一串字,我希望匹配三元组(wrd)。我正在使用CONTAINS进行单词顺序独立

  1. 在Cypher中有更好的方法吗?
  2. RDBMS是否可以更好地解决此问题?

1 个答案:

答案 0 :(得分:2)

纯粹是为了简化Cypher查询本身(不一定是性能)而已,如果您可以将要搜索的单词收集到列表列表中,那么无论有多少单词或多少集合,查询都可以保持稳定。

这是一个例子:

// below for example input, though you would want to parameterize this
WITH [['wrd1-1', 'wrd1-2', 'wrd1-3'], ['wrd2-1', 'wrd2-2', 'wrd2-3'], ['wrd3-1', 'wrd3-2', 'wrd3-3']] as searchData
MATCH (n:Node) // or whatever type you're matching on
UNWIND searchData as words
WITH n 
WHERE all(word IN words WHERE n.val CONTAINS word) 
RETURN n

最后一个使用all()谓词功能的WHERE子句将确保CONTAINS检查对于该集合中的所有单词在该节点上必须为true。

就性能而言,您提到使用CONTAINS来实现字序独立性。如果val属性仅包含整个单词,而您的目标是仅查找该属性中的整个单词,那么可以通过几种不同的方法来处理。

如果val属性中当前的单词数与您要搜索的单词数相同(例如,始终为3个单词,那么您将始终在其中搜索相同的3个单词),则您可以重构数据,以使val始终按字母顺序排列并小写,然后对该属性进行索引,以便在执行查找时可以将输入更改为相同的格式(小写和字母)并执行精确的查找,这将利用索引。

如果您需要能够查询节点上单词的子集(但是您仍然只在查找整个单词),则可以考虑重构数据,以代替{{1} }属性在您的节点上,单词变成了与原始节点有关系的自己的节点。

这样,您可以对:Word节点执行索引查找,然后从中查找与与所有匹配的:Word节点都有关系的节点。

这里有一个article on performing match intersection,说明了解决此类匹配的几种方法。