【问题标题】:Neo4j/cypher query optiminzationNeo4j/cypher 查询优化
【发布时间】:2015-05-22 14:49:32
【问题描述】:

下面的查询试图在一个本体中查找一个概念的所有子类型。一旦识别了所有概念,查询将尝试识别层次结构中定义为“原始”(属性定义StatusId)并且具有定义为“完全定义”的超类型和子类型概念的所有概念(使用相同的属性定义StatusId) .

层次结构中的概念数为 101,000(几百万条路径),“原始”概念总数 = 56,000,非叶节点基元总数 = 13,000。

执行查询时 webadmin 挂起。所以,显然写得不好。我试图在每一步都缩小查询的范围,但我肯定做得不对!

建议?

//Find all clinical finding subtypes
MATCH (a:ObjectConcept{sctid:404684003})<-[:ISA*]-(b:ObjectConcept)
with collect (DISTINCT b) as set1
//Find all primitive subtypes of clinical findings
UNWIND set1 as x1
MATCH x1
WHERE x1.definitionStatusId = 900000000000074008
with collect (DISTINCT x1) as prim,set1
//Find all fully-defined subtypes of clinical findings
UNWIND set1 as x2
MATCH x2
WHERE x2.definitionStatusId = 900000000000073002
with collect (DISTINCT x2) as full, prim
//Find all primitives with a fully-defined subtype
UNWIND prim as prim1
UNWIND full as full1
MATCH prim1,full1
WHERE EXISTS((prim1)<-[:ISA*]-(full1)) as prim11
with collect (DISTINCT prim11) as intprim, full1
//Find all high level primitives with a fully-defined supertype
UNWIND intprim as intprim1
MATCH intprim1,full1
WHERE EXISTS((full1)<-[:ISA*]-(intprim1)) as intprim11
with collect (DISTINCT intprim11) as intprim2
//Find all high level primitives with fully defined supertypes
//that also have fully defined subtypes
UNWIND intprim2 as intprim22
return intprim22.sctid,intprim22.FSN

【问题讨论】:

  • 嗨,斯科特,有几件事:你能分享你的数据库吗?你能尝试更好地命名你的变量吗?为什么不早点过滤 definitionStatusId ?不需要 MATCH (x1)。否则马丁说的:)

标签: neo4j cypher


【解决方案1】:

您的查询看起来很复杂。如果我理解正确,您希望找到所有“原始”的ObjectConcept 节点并且具有“完全定义”的父子节点:

(ObjectConcept "fully defined")
   |
[:ISA]
   |
(ObjectConcept "primitive")  <-- find this?
   |
[:ISA]
   |
(ObjectConcept "fully defined")

我认为你可以简单地匹配:

MATCH (oc_parent:ObjectConcept {definitionStatusId: 'fully'})-[:ISA]->
      (oc:ObjectConcept {definitionStatusId: 'primitive'})-[:ISA]->
      (oc_child:ObjectConcept {definitionStatusId: 'fully'})
RETURN oc_parent, oc, oc_child

所有DISTINCTcollect()UNWIND 不一定会使您的查询更快。

你应该在definitionStatusId上有一个索引:

CREATE INDEX ON :ObjectConcept(definitionStatusId)

更新

您可以先在子层次结构中查询ObjectConcepts,但[:ISA*] 查询可能会查找很长的路径并且可能非常昂贵。 300.000 个节点并不多,所以第一个解决方案实际上可能更快。只有当你真的必须过滤节点的子集时,我才会这样做。

// get the sub-hierarchy first
MATCH (:ObjectConcept {sctid:404684003})<-[:ISA*]-(oc:ObjectConcept {definitionStatusId: 'primitive'})
WITH oc
MATCH (oc_parent:ObjectConcept {definitionStatusId: 'fully'})-[:ISA]->
      (oc)-[:ISA]->
      (oc_child:ObjectConcept {definitionStatusId: 'fully'})
RETURN oc_parent, oc, oc_child

【讨论】:

  • 谢谢,马丁。我在 :ObjectConcept(definitionStatusId) 上确实有一个索引,您确实理解我的查询,但有一个例外。 ObjectConcepts 的总“池”是 300,000 个节点。因此,我首先需要获取感兴趣的子层次结构中的概念。这是 (a)
  • 嗯好的。我还使用具有相似数量节点的本体。从给定起点解析层次结构不应花费 20 分钟。路径有多长?
  • 此子层次结构中的最长路径至少为 14 个节点。使用 groovy 代码可以更快地遍历层次结构,但我更喜欢使用 cypher。 Groovy 可以在 1 分钟内完成这些遍历。
  • 我现在正在运行这个查询: MATCH (a:ObjectConcept{sctid:404684003})
  • 好吧,你不需要收集/展开。只需RETURN DISTINCT c.sctid, c.FSN
【解决方案2】:

以下查询产生了一个有效的答案,而不会使网络浏览器崩溃。然而,它仍然需要很长时间才能完成。因此,需要进行额外的优化。

//Find all subtypes of ObjectConcept
MATCH (a:ObjectConcept{sctid:404684003})<-[:ISA*]-(b:ObjectConcept{definitionStatusId:900000000000074008})
//Remove duplicate nodes
with distinct(b) as prim
//Remove leaf nodes
MATCH (prim)<-[:ISA*1..1]-()
with distinct(prim) as prim1
//Find all intermediate primitive nodes satisfying the requirements
MATCH (c:ObjectConcept{definitionStatusId:900000000000073002})<-[:ISA*]-(prim1)<-[:ISA*]-(d:ObjectConcept{definitionStatusId:900000000000073002})
return DISTINCT prim1.sctid,prim1.FSN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多