如何编写筛选遍历元素的查询

时间:2015-07-30 05:07:07

标签: orientdb

我正在努力解决以下问题。对于家谱树数据库,我有一个顶点' Person'并且是一个轻量级的边缘' Child&#39 ;,因此边缘将从父母和孩子(即' child-of')中消失。对于一个人,我需要让他们的兄弟姐妹分享完全相同的父母。

我可以让所有兄弟姐妹相当容易,如下所示;

SELECT 
FROM (
    TRAVERSE out_Child
    FROM (
        SELECT expand(in_Child)
        FROM #11:3
    )
    WHILE $depth <= 1
)
WHERE $depth = 1

所以这会得到有关人员的父母,然后得到父母的所有孩子。结果可能如下所示

@rid    in_Child
#11:2  #11:0
#11:3  #11:0, #11:1
#11:4  #11:0, #11:1
#11:5  #11:1

我需要过滤这些结果,因为我只想要与#11:3具有完全相同父级的记录。所以在这种情况下,查询应该只返回#11:3和#11:4。如果查询是针对#11:5,则它应仅返回#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

最终我宁愿不做任何子查询,但如果需要,那么就这样吧。我也尝试使用traversedElement(0)函数,但它只返回遍历的第一个记录(即#11:0,但不是#11:1),因此无法使用它。

更新; 如果将以下内容复制粘贴到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

2 个答案:

答案 0 :(得分:0)

动态父母数量的更新:

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)

答案 1 :(得分:0)

好的,我找到了一些解决方案。

首先,正如我所指出的here,我在问题中使用CONTAINSALL的方式并不正确。 CONTAINSALL不会检查&#39;右边的所有项目。在&#39; left&#39;中,但实际上是在&#39; left&#39;中的每个项目上循环并在&#39;右边的表达式中使用该项目。 SO 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可能有错误。上面的查询返回#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)

效果更好。上述查询正确返回#11:3和#11:4,但#11:2或#11:5上的查询也错误地包含#11:3和#11:4。这是有道理的,因为它检查例如#11:2(仅为1)的父rid是在其余的父母中,他们是。所以我加了一张支票,以确保他们有相同数量的父母。

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()

这似乎是最好/最安全的,也是我将使用的那个。