使用OrientDB SQL查找“朋友的朋友”

使用OrientDB SQL查找“朋友的朋友”,orientdb,Orientdb,虽然这是演示图形数据库功能的最常见的用例之一,但我似乎找不到一个好的示例或最佳实践来使用OrientDB SQL获得朋友的朋友 让我们假设一个社交网络,并尝试用用户顶点对其进行建模,并且是有边的朋友 定义: 具有uuid自定义唯一id和名称属性的Vertex类用户 边缘类的属性状态可以是挂起的或已批准的 用户通过单向边缘相互连接。方向并不重要;只要status=approved,这两个用户就是朋友 这是我提出的一个解决方案: select from ( select expand($al

虽然这是演示图形数据库功能的最常见的用例之一,但我似乎找不到一个好的示例或最佳实践来使用OrientDB SQL获得朋友的朋友

让我们假设一个社交网络,并尝试用用户顶点对其进行建模,并且是有边的朋友

定义:

具有uuid自定义唯一id和名称属性的Vertex类用户

边缘类的属性状态可以是挂起的或已批准的

用户通过单向边缘相互连接。方向并不重要;只要status=approved,这两个用户就是朋友

这是我提出的一个解决方案:

select from (
    select expand($all) let
        $a = (select expand(outE('is_friend_with')[status='approved'].inV('user').outE('is_friend_with')[status='approved'].inV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
        $b = (select expand(outE('is_friend_with')[status='approved'].inV('user').inE('is_friend_with')[status='approved'].outV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
        $c = (select expand(inE('is_friend_with')[status='approved'].outV('user').inE('is_friend_with')[status='approved'].outV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
        $d = (select expand(inE('is_friend_with')[status='approved'].outV('user').outE('is_friend_with')[status='approved'].inV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
        $all = unionall($a, $b, $c, $d)
) where uuid <> '95920a96a60c4d40a8f70bde98ae1a24'
uuid='95920a96a60c4d40a8f70bde98ae1a24'的用户是起点

但是,我觉得它不太优雅。我可以立即发现的一些问题是:

重复从用户选择,其中uuid='95920a96a60c4d40a8f70bde98ae1a24'。不幸的是,我无法找到一种方法将其分配给变量,然后在from子句中使用它 我被迫进行传入/传出边/顶点的所有组合,而不是同时使用两者,因为我想检查每个边的状态=已批准 此查询还返回直接好友,而不是仅返回好友的好友 我尝试使用traverse,但再次无效,在遍历时找不到如何检查边的status=approved的方法

您能为这个问题提出一些OSQL解决方案吗?提前谢谢。

你试过这个吗

select 
      expand(bothE('is_friend_with')[status = 'approved'].inV().bothE('is_friend_with')[status = 'approved'].inV()) 
from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'

也许有更好的方法,但我认为这会给你你想要的:

设置:

查询:

编辑2:改用变量

 select from (
      select 
        expand(unionall(
          outE("IsFriendsWith")[status="approved"].inV(), 
          inE("IsFriendsWith")[status="approved"].outV()
        ))
        from (
          select 
              expand(unionall(
                outE("IsFriendsWith")[status="approved"].inV(), 
                inE("IsFriendsWith")[status="approved"].outV()
              ))
          from (
             select expand($u) let $u = first((select from User where uuid = "1"))
          )
        )
    )
  )
  where @rid <> $u and @rid NOT IN $u.both("IsFriendsWith")

这应该简单得多:

select expand(
  bothE('is_friend_with')[status = 'approved'].bothV()
  .bothE('is_friend_with')[status = 'approved'].bothV()
) from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'
使用bothE和bothV,可以在边/顶点级别获得两个输入/输出连接

为了排除当前用户,您可以使用:

select expand(
  bothE('is_friend_with')[status = 'approved'].bothV()
  .bothE('is_friend_with')[status = 'approved'].bothV()
  .remove( @this )
) from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'

谢谢你的回答,@codemix。它工作正常,比我的解决方案优雅得多。但是,该查询也返回了我们不感兴趣的直接朋友。我尝试了通过执行create edge IsFriendsWith from select from User,其中uuid=2,以select from User,其中uuid=6,set status=approved。你是否知道如何过滤掉直接的朋友,只返回朋友的建议朋友?我没有尝试过,但现在看起来不错。因为我想远离@rid,我想我应该用select from User重写查询,其中uuid=xxx。虽然会有重复,但指数会被击中,所以不会有问题。如果可能的话,您是否知道如何将select赋值给变量并在from子句中重用它?。非常感谢,@codemix,我会接受这个答案。谢谢你的例子。正如@codemix所指出的,inV只在一个方向上限制遍历。
 select from (
      select 
        expand(unionall(
          outE("IsFriendsWith")[status="approved"].inV(), 
          inE("IsFriendsWith")[status="approved"].outV()
        ))
        from (
          select 
              expand(unionall(
                outE("IsFriendsWith")[status="approved"].inV(), 
                inE("IsFriendsWith")[status="approved"].outV()
              ))
          from (
             select expand($u) let $u = first((select from User where uuid = "1"))
          )
        )
    )
  )
  where @rid <> $u and @rid NOT IN $u.both("IsFriendsWith")
select expand(
  bothE('is_friend_with')[status = 'approved'].bothV()
  .bothE('is_friend_with')[status = 'approved'].bothV()
) from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'
select expand(
  bothE('is_friend_with')[status = 'approved'].bothV()
  .bothE('is_friend_with')[status = 'approved'].bothV()
  .remove( @this )
) from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'