繁体   English   中英

在Neo4j中,可以找到其关系是另一个节点关系的超集的所有节点吗?

[英]In Neo4j, can one find all nodes whose relationships are a superset of another node's relationships?

鉴于以下人为的数据库:

CREATE (a:Content {id:'A'}),
  (b:Content {id:'B'}),
  (c:Content {id:'C'}),
  (d:Content {id:'D'}),
  (ab:Container {id:'AB'}),
  (ab2:Container {id:'AB2'}),
  (abc:Container {id:'ABC'}),
  (abcd:Container {id:'ABCD'}),
  ((ab)-[:CONTAINS]->(a)),
  ((ab)-[:CONTAINS]->(b)),
  ((ab2)-[:CONTAINS]->(a)),
  ((ab2)-[:CONTAINS]->(b)),
  ((abc)-[:CONTAINS]->(a)),
  ((abc)-[:CONTAINS]->(b)),
  ((abc)-[:CONTAINS]->(c)),
  ((abcd)-[:CONTAINS]->(a)),
  ((abcd)-[:CONTAINS]->(b)),
  ((abcd)-[:CONTAINS]->(c)),
  ((abcd)-[:CONTAINS]->(d))

是否有一个查询可以检测所有Container节点对,其中一个CONTAINS是另一个Container节点的超集或相同的Content节点?

对于我的示例数据库,我希望查询返回:

(ABCD) is a superset of (ABC), (AB), and (AB2)
(ABC) is a superset of (AB), and (AB2)
(AB) and (AB2) contain the same nodes

如果cypher不适合这个,但另一种查询语言非常适合它,或者如果Neo4j不适合这个,但另一个数据库非常适合它,我也很感激它的输入。

可视化示例数据库

回答查询表现 (截至2017-02-28T21:56Z)

我没有经验,Neo4j或图形DB查询分析答案的性能,我还没有构建我的大数据集进行更有意义的比较,但我想我会用PROFILE命令和列表运行每一个数据库命中成本。 我省略了时序数据,因为我无法使这么小的数据集保持一致或有意义。

  • stdob--:129 db db hits
  • Dave Bennett:总共有46次点击
  • InverseFalcon:共有27个db命中
// Get contents for each container
MATCH (SS:Container)-[:CONTAINS]->(CT:Content)
      WITH SS, 
           collect(distinct CT) as CTS
// Get all container not equal SS
MATCH (T:Container) 
      WHERE T <> SS
// For each container get their content
MATCH (T)-[:CONTAINS]->(CT:Content)
      // Test if nestd
      WITH SS, 
      CTS, 
      T, 
      ALL(ct in collect(distinct CT) WHERE ct in CTS) as test 
      WHERE test = true
RETURN SS, collect(T)

这是第一次尝试。 我相信这可以使用一些改进,但这应该让你去。

// find the containers and their contents
match (n:Container)-[:CONTAINS]->(c:Content)

// group the contents per container
with n as container, collect(c.id) as contents

// combine the continers and their contents
with collect(container{.id, contents: contents}) as containers

// loop through the list of containers
with containers, size(containers) as container_size
unwind range(0, container_size -1) as i
unwind range(0, container_size -1) as j

// for each container pair compare the contents
with containers, i, j
where i <> j
and all(content IN containers[j].contents WHERE content in containers[i].contents)
with containers[i].id as superset, containers[j].id as subset
return superset, collect(subset) as subsets

在获取容器及其收集的内容之后,我将使用的方法是过滤掉哪些容器通过其内容的计数相互比较,然后从APOC过程运行apoc.coll.containsAll()来过滤超集/同等集。 最后,您可以比较内容的计数,以确定它是超集还是同等集,然后收集。

像这样的东西:

match (con:Container)-[:CONTAINS]->(content)
with con, collect(content) as contents
with collect({con:con, contents:contents, size:size(contents)}) as all
unwind all as first
unwind all as second
with first, second
where first <> second and first.size >= second.size
with first, second
where apoc.coll.containsAll(first.contents, second.contents)
with first, 
 case when first.size = second.size and id(first.con) < id(second.con) then second end as same, 
 case when first.size > second.size then second end as superset
with first.con as container, collect(same.con) as sameAs, collect(superset.con) as supersetOf
where size(sameAs) > 0 or size(supersetOf) > 0
return container, sameAs, supersetOf
order by size(supersetOf) desc, size(sameAs) desc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM