在Neo4j中,可以找到其关系是另一个节点的超集的所有节点吗';谁的关系?
鉴于以下人为数据库:在Neo4j中,可以找到其关系是另一个节点的超集的所有节点吗';谁的关系?,neo4j,cypher,Neo4j,Cypher,鉴于以下人为数据库: 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
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))
是否有一个查询可以检测所有容器
节点对,其中一个包含与另一个容器
节点相同的内容
节点的超集
对于我的示例数据库,我希望查询返回:
(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-28221:56Z)
我在Neo4j或graph DB查询方面还没有足够的经验来分析答案的性能,我还没有构建大型数据集来进行更有意义的比较,但我认为我应该使用PROFILE命令运行每个数据集,并列出DB命中成本。我省略了计时数据,因为我无法使它与如此小的数据集保持一致或有意义
- stdob--:129总db命中率
- 戴夫·贝内特:总命中率46分贝
- 反向频率:27 db总命中率
这是第一次尝试。我相信这可能需要一些改进,但这应该让你去
// 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
//查找容器及其内容
匹配(n:Container)-[:CONTAINS]->(c:Content)
//将每个容器中的内容分组
使用n作为容器,收集(c.id)作为内容物
//结合容器及其内容物
使用collect(容器{.id,contents:contents})作为容器
//循环浏览容器列表
对于容器,大小(容器)为容器大小
展开范围(0,容器大小-1)为i
放卷范围(0,容器尺寸-1)为j
//对于每个容器对,比较内容
对于容器,i,j
我在哪里
和全部(容器中的内容[j]。其中容器中的内容[i]。内容)
容器[i].id作为超集,容器[j].id作为子集
返回超集,收集(子集)作为子集
//获取每个容器的内容
匹配(SS:容器)-[:包含]->(CT:内容)
有党卫军,,
将(不同的CT)收集为CT
//使所有容器不等于SS
匹配(T:容器)
在哪里
//对于每个容器,获取其内容
匹配(T)-[:包含]->(CT:内容)
//测试是否嵌套
有党卫军,,
中旅,
T
全部(ct在采集中(不同ct),其中ct在ct中)作为测试
其中test=true
返回SS,收集(T)
在获取容器及其收集的内容后,我将使用的方法是通过内容计数筛选出哪些容器彼此比较,然后运行以筛选超集/相等集。最后,您可以比较内容的计数,以确定它是超集还是相等集,然后收集
大概是这样的:
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
匹配(con:Container)-[:CONTAINS]->(content)
使用con,将(内容)收集为内容
使用collect({con:con,contents:contents,size:size(contents)})作为所有
先把所有的东西都解开
以秒为单位全部展开
第一,第二
其中first second和first.size>=second.size
第一,第二
其中apoc.coll.containsAll(first.contents,second.contents)
首先,
当first.size=second.size且id(first.con)second.size然后第二个end作为超集时的情况
使用first.con作为容器,collect(same.con)作为sameAs,collect(superset.con)作为supersetOf
其中大小(sameAs)>0或大小(supersetOf)>0
返回容器,sameAs,supersetOf
按尺寸(超级)说明订购,尺寸(相同)说明
Dave Bennett和stdob的回答似乎都给出了我要求的结果,谢谢。我对这两个都投了赞成票,一旦我在一个更大的数据集上尝试了它们,我就会给出一个答案,因为我不得不选择一个。关于在更大的数据集中有多少容器节点?我还没有组装它(这需要做一些工作,现在我知道我有可行的工具来完成后面的计算,这是我议程上的下一步)。然而,70000个集装箱似乎是一个现实的估计。每个容器的容量从几个到几百个不等,但平均可能有30个。
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