我一直在为neo4j玩一个基因学网站而且效果很好!
我遇到了一个问题,那里找到起始节点并不容易。通过在线查看文档和帖子,我没有看到任何暗示这一点,所以也许这是不可能的。
我想要做的是传递一个性别列表,然后从该列表中按照节点中的特定路径获取单个节点。
在家庭背景下:
我想得到我母亲的父亲母亲的母亲。所以我有我的身份所以我会从那里开始并从我的四个节点遍历。
所以伪查询将是
select person (follow childof relationship)
where starting node is me
where firstNode.gender == female
AND secondNode.gender == male
AND thirdNode.gender == female
AND fourthNode.gender == female
答案 0 :(得分:2)
关注一般解决方案:
MATCH p = (me:Person)-[:IS_CHILD_OF*]->(ancestor:Person)
WHERE me.uuid = {uuid}
AND length(p) = size({genders})
AND extract(x in tail(nodes(p)) | x.gender) = {genders}
RETURN ancestor
这是它的工作原理:
nodes(p)
返回路径中的所有节点,包括起始节点tail(nodes(p))
跳过列表的第一个元素,即起始节点,所以现在我们只有祖先extract()
提取所有祖先节点的性别,即它将祖先节点列表转换为其性别但是,我认为它不会比显式解决方案更快,尽管性能可以保持可比性。在我的小测试数据(仅5个节点)上,一般解决方案执行26次DB访问,而特定解决方案仅执行22次,如PROFILE
所报告。在较大的数据库上需要进一步分析以比较性能:
PROFILE MATCH p = (me:Person)-[:IS_CHILD_OF*]->(ancestor:Person)
WHERE me.uuid = {uuid}
AND length(p) = size({genders})
AND extract(x in tail(nodes(p)) | x.gender) = {genders}
RETURN ancestor
通用解决方案的优点是可以通过Cypher引擎再次解析单个查询,而每个生成的查询都需要进行解析。
答案 1 :(得分:1)
这比我想象的要简单。也许还有更好的方法,所以我会稍微开放一下。
查询将是
MATCH (n1:Person { Id: 'f59c40de-506d-4829-a765-7a3ae94af8d1' })
<-[:CHILDOF]-(n2 { Gender:'0'})
<-[:CHILDOF]-(n3 { Gender:'1'})
<-[:CHILDOF]-(n4 { Gender:'1'})
RETURN n4
并且每回一代都会添加一个新行。
答案 2 :(得分:1)
等效查询看起来像这样:
MATCH (me:Person)
WHERE me.ID = ?
WITH me
MATCH (me)-[r:childof*4]->(ancestor:Person)
WITH ancestor, EXTRACT(rel IN r | endNode(rel).gender) AS genders
WHERE genders = ?
RETURN ancestor
免责声明,我没有仔细检查语法。
在Neo4j中,您通常首先找到您的起始节点,通常是某种ID(根据需要进行修改以匹配唯一属性)。然后,我们遍历一系列与祖先的关系,提取遍历关系中所有终端节点的性别属性,并将性别与预期的性别列表进行比较(您需要确保参数是括号列表按期望的顺序)。
请注意,这种方法会过滤掉所有可能的结果,而不是走路图,所以关系程度越高(您查询的祖先程度越高),呼叫的速度就越慢得到。
我也不确定你是否可以参数化变量关系的程度,这可能会阻止它成为任何程度的祖先的通用解决方案。
答案 3 :(得分:1)
我不确定您是否想要一个通用查询,它可以处理您传递的性别集合或特定解决方案。
以下是具体的解决方案:您将路径与所需长度匹配,并匹配每个性别,如您在自己的答案中所述。
MATCH (me:Person)-[:IS_CHILD_OF]->(p1:Person)
-[:IS_CHILD_OF]->(p2:Person)
-[:IS_CHILD_OF]->(p3:Person)
-[:IS_CHILD_OF]->(p4:Person)
WHERE me.uuid = {uuid}
AND p1.gender = {genders}[0]
AND p2.gender = {genders}[1]
AND p3.gender = {genders}[2]
AND p4.gender = {genders}[3]
RETURN p4
现在,如果你想传入一个任意长度的性别列表,它实际上是可能的。您匹配可变长度路径,确保它具有正确的长度(匹配性别数),然后按顺序匹配每个性别。
MATCH p = (me:Person)-[:IS_CHILD_OF*]->(ancestor:Person)
WHERE me.uuid = {uuid}
AND length(p) = size({genders})
AND all(i IN range(0, size({genders}) - 1)
WHERE {genders}[i] = extract(x in tail(nodes(p)) | x.gender)[i])
RETURN ancestor
在@ InverseFalcon的答案基础上,您可以实际比较集合,从而简化查询:
MATCH p = (me:Person)-[:IS_CHILD_OF*]->(ancestor:Person)
WHERE me.uuid = {uuid}
AND length(p) = size({genders})
AND extract(x in tail(nodes(p)) | x.gender) = {genders}
RETURN ancestor