如何编写过滤遍历元素的查询
How to write a query that filters traversed elements
我正在努力处理以下查询。对于家谱数据库,我有一个顶点 'Person' 和一个轻量级边 'Child',所以边会从 parent 出来并进入 child(即 'child-of').从一个人那里,我需要得到他们共享完全相同 parents.
的兄弟姐妹
我可以相当容易地得到一个人的所有兄弟姐妹,如下所示;
SELECT
FROM (
TRAVERSE out_Child
FROM (
SELECT expand(in_Child)
FROM #11:3
)
WHILE $depth <= 1
)
WHERE $depth = 1
所以这得到了相关人员的parents,然后得到了parents的所有children。结果可能如下所示
@rid in_Child
#11:2 #11:0
#11:3 #11:0, #11:1
#11:4 #11:0, #11:1
#11:5 #11:1
不过我需要过滤这些结果,因为我只想要 parent 与 #11:3 完全相同的记录。所以在这种情况下,查询应该只有 return #11:3 和 #11:4。如果查询的是#11:5,它应该只 return #11:5。所以基本上,in_Child 字段必须相同。
我已经尝试了各种查询,例如以下,但查询没有 运行 或没有过滤。
SELECT
FROM (
SELECT
FROM (
TRAVERSE out_Child
FROM (
SELECT expand(in_Child)
FROM #11:3
)
WHILE $depth <= 1
)
WHERE $depth = 1
)
LET $testinChild = (SELECT expand(in_Child) FROM #11:3)
WHERE in_Child CONTAINSALL $testinChild
最终我宁愿不做任何事情 sub-queries,但如果需要,那就这样吧。我也试过使用traversedElement(0)
函数,但是它只是return遍历的第一条记录(即#11:0,而不是#11:1),所以不能使用。
更新;
如果您 copy-paste 将以下内容输入到 orientdb 控制台(更改密码等以适合您的设置),您将拥有与上述相同的数据集。
create database remote:localhost/persondb root pass memory graph
alter database custom useLightweightEdges=true
create class Person extends V
create property Person.name string
create class Child extends E
create vertex Person set name = "Father"
create vertex Person set name = "Mother"
create vertex Person set name = "Child of father only"
create edge Child from #11:0 to #11:2
create vertex Person set name = "Child of father+mother #1"
create edge Child from #11:0 to #11:3
create edge Child from #11:1 to #11:3
create vertex Person set name = "Child of father+mother #2"
create edge Child from #11:0 to #11:4
create edge Child from #11:1 to #11:4
create vertex Person set name = "Child of mother only"
create edge Child from #11:1 to #11:5
parents 的动态数字的更新:
SELECT
distinct(@rid)
FROM
(SELECT
expand(intersect)
FROM
(SELECT
in('Child').out('Child') as intersect
FROM
#17:2))
WHERE
in('Child').size() = $parentCount.size[0]
LET $parentCount = (SELECT
in('Child').size() as size
FROM
#17:2)
好的,我找到了一些解决方案。
首先,正如我所指出的那样,我在问题中使用 CONTAINSALL 的方式是不正确的 here。 CONTAINSALL 不检查 'right' 上的所有项目都在 'left' 中,但实际上循环遍历 'left' 中的每个项目并在 'right' 上的表达式中使用该项目].因此 WHERE in_Child CONTAINSALL (sex = 'Male)
将过滤所有 in_Child 记录均为男性(即没有女性)的记录。它基本上是在检查 in_Child[0:n].sex = 'Male'
.
所以我尝试了这个查询;
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
WHERE
(SELECT expand(in('Child')) from #11:3) CONTAINSALL (@rid in $current.in_Child)
我认为 OrientDB 在这里可能有一个错误。上面的查询 return #11:2、#11:3 和 #11:4,这对我来说没有意义。我稍微更改了此查询...
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
$parents CONTAINSALL (@rid in $current.in_Child)
这样效果更好。上面的查询正确 returns #11:3 和 #11:4,但是对 #11:2 或 #11:5 的查询也错误地包含了 #11:3 和 #11:4。这是有道理的,因为它检查 parent 删除例如 #11:2(只有 1)在其余的 parent 中,它们是。所以我添加了一张支票以确保他们有相同数量的 parents.
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
$parents CONTAINSALL (@rid in $current.in_Child)
AND
$parents.size() = in('Child').size()
现在查询对所有实例都正常工作。但是,我仍然对这个查询不满意。我放弃了使用 CONTAINSALL 并最终想出了以下...
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
in_Child.asSet() = $parents.asSet()
这是 best/safest,我将使用它。
我正在努力处理以下查询。对于家谱数据库,我有一个顶点 'Person' 和一个轻量级边 'Child',所以边会从 parent 出来并进入 child(即 'child-of').从一个人那里,我需要得到他们共享完全相同 parents.
的兄弟姐妹我可以相当容易地得到一个人的所有兄弟姐妹,如下所示;
SELECT
FROM (
TRAVERSE out_Child
FROM (
SELECT expand(in_Child)
FROM #11:3
)
WHILE $depth <= 1
)
WHERE $depth = 1
所以这得到了相关人员的parents,然后得到了parents的所有children。结果可能如下所示
@rid in_Child
#11:2 #11:0
#11:3 #11:0, #11:1
#11:4 #11:0, #11:1
#11:5 #11:1
不过我需要过滤这些结果,因为我只想要 parent 与 #11:3 完全相同的记录。所以在这种情况下,查询应该只有 return #11:3 和 #11:4。如果查询的是#11:5,它应该只 return #11:5。所以基本上,in_Child 字段必须相同。
我已经尝试了各种查询,例如以下,但查询没有 运行 或没有过滤。
SELECT
FROM (
SELECT
FROM (
TRAVERSE out_Child
FROM (
SELECT expand(in_Child)
FROM #11:3
)
WHILE $depth <= 1
)
WHERE $depth = 1
)
LET $testinChild = (SELECT expand(in_Child) FROM #11:3)
WHERE in_Child CONTAINSALL $testinChild
最终我宁愿不做任何事情 sub-queries,但如果需要,那就这样吧。我也试过使用traversedElement(0)
函数,但是它只是return遍历的第一条记录(即#11:0,而不是#11:1),所以不能使用。
更新; 如果您 copy-paste 将以下内容输入到 orientdb 控制台(更改密码等以适合您的设置),您将拥有与上述相同的数据集。
create database remote:localhost/persondb root pass memory graph
alter database custom useLightweightEdges=true
create class Person extends V
create property Person.name string
create class Child extends E
create vertex Person set name = "Father"
create vertex Person set name = "Mother"
create vertex Person set name = "Child of father only"
create edge Child from #11:0 to #11:2
create vertex Person set name = "Child of father+mother #1"
create edge Child from #11:0 to #11:3
create edge Child from #11:1 to #11:3
create vertex Person set name = "Child of father+mother #2"
create edge Child from #11:0 to #11:4
create edge Child from #11:1 to #11:4
create vertex Person set name = "Child of mother only"
create edge Child from #11:1 to #11:5
parents 的动态数字的更新:
SELECT
distinct(@rid)
FROM
(SELECT
expand(intersect)
FROM
(SELECT
in('Child').out('Child') as intersect
FROM
#17:2))
WHERE
in('Child').size() = $parentCount.size[0]
LET $parentCount = (SELECT
in('Child').size() as size
FROM
#17:2)
好的,我找到了一些解决方案。
首先,正如我所指出的那样,我在问题中使用 CONTAINSALL 的方式是不正确的 here。 CONTAINSALL 不检查 'right' 上的所有项目都在 'left' 中,但实际上循环遍历 'left' 中的每个项目并在 'right' 上的表达式中使用该项目].因此 WHERE in_Child CONTAINSALL (sex = 'Male)
将过滤所有 in_Child 记录均为男性(即没有女性)的记录。它基本上是在检查 in_Child[0:n].sex = 'Male'
.
所以我尝试了这个查询;
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
WHERE
(SELECT expand(in('Child')) from #11:3) CONTAINSALL (@rid in $current.in_Child)
我认为 OrientDB 在这里可能有一个错误。上面的查询 return #11:2、#11:3 和 #11:4,这对我来说没有意义。我稍微更改了此查询...
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
$parents CONTAINSALL (@rid in $current.in_Child)
这样效果更好。上面的查询正确 returns #11:3 和 #11:4,但是对 #11:2 或 #11:5 的查询也错误地包含了 #11:3 和 #11:4。这是有道理的,因为它检查 parent 删除例如 #11:2(只有 1)在其余的 parent 中,它们是。所以我添加了一张支票以确保他们有相同数量的 parents.
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
$parents CONTAINSALL (@rid in $current.in_Child)
AND
$parents.size() = in('Child').size()
现在查询对所有实例都正常工作。但是,我仍然对这个查询不满意。我放弃了使用 CONTAINSALL 并最终想出了以下...
SELECT
FROM (
SELECT
FROM (
TRAVERSE
out('Child')
FROM (
SELECT
expand(in('Child'))
FROM
#11:3
)
WHILE
$depth <= 1
)
WHERE
$depth = 1
)
LET
$parents = (SELECT expand(in('Child')) from #11:3)
WHERE
in_Child.asSet() = $parents.asSet()
这是 best/safest,我将使用它。