关于无向边的SetAccum

点a和点b,有一条无向边e。在遍历时将边加入到一个SetAccum时,遍历时a到b和b到a会被认为是两条不一样的边,应该怎样使得a-b和b-a被认为是同一条边。

无向边可以理解成2条有向边。
不过我在想,您会遇到这个问题,是否是因为遇到了环?一般查询中,是要避免环的,更多请参考https://community.tigergraph.com.cn/t/topic/375/2

不是,我要返回遍历边的jason给前台,使用的是@@SetAccum,我希望对于无向边,无论访问方向,SetAccum里面有的是一条边,毕竟这是一条无向边,否则前台还需做去重操作。或者还有别的方案?

您可以考虑只向@@SetAccum中加入符合“起点的internal id > 终点的internal id”的条件的边。
比如像如下的代码:

CREATE QUERY test2(
VERTEX<customer> a_cust,
VERTEX<orders> an_order) FOR GRAPH TPC_H { 
  /** Example input:
   *  a_cust 7334044,
   *  an_order 537438624
   **/
  SetAccum<EDGE> @@edgeSet;
  Customers = {a_cust};
  Orders = {an_order};
  Customers =
    SELECT s
    FROM   Customers:s -(:e)- orders:t
    WHERE  t == an_order
           AND getvid(t) > getvid(s)
    ACCUM  @@edgeSet += e
  ;
  Orders =
    SELECT s
    FROM   Orders:s -(:e)- customer:t
    WHERE  t == a_cust
           AND getvid(t) > getvid(s)
    ACCUM  @@edgeSet += e
  ;
  PRINT @@edgeSet;
}

这个方案的话,需要两个方向(a–>b 和 b–>a)都访问过才能保证edge一定能加进去,不然会导致丢边,还有其他方案吗?

您在什么场景下会遇到这种情况?

一个点3度可以访问到的所有点和相关的边

这种场景只要把访问过的顶点标记下,然后下一跳的时候不要跳已经标记过的顶点就可以解决了。跟前面提到的避免环的问题是一样的。

标记访问点的方法是无法找到所有边的,因为到达一个点可能的路径度数不一样,设为已经访问会使高度的路径无法得到。

还是类似前面符合“起点的internal id > 终点的internal id”的条件的边的案例,将判定条件放在accum的if,这样可以满足您的需求吗?比如像这样:

CREATE QUERY test2(
VERTEX<customer> a_cust,
VERTEX<orders> an_order) FOR GRAPH TPC_H { 
  /** Example input:
   *  a_cust 7334044,
   *  an_order 537438624
   **/
  SetAccum<EDGE> @@edgeSet;
  Customers = {a_cust};
  Orders = {an_order};
  Customers =
    SELECT s
    FROM   Customers:s -(:e)- orders:t
    WHERE  t == an_order
    ACCUM  IF getvid(t) > getvid(s) THEN @@edgeSet += e END
  ;
  Orders =
    SELECT s
    FROM   Orders:s -(:e)- customer:t
    WHERE  t == a_cust
    ACCUM  IF getvid(t) > getvid(s) THEN @@edgeSet += e END
  ;
  PRINT @@edgeSet;
}

谢谢解答,不过还是不行,因为起点是一个点,终点是可能的所有点,做双向访问的话,代价太高,不做双向访问的话,还是会漏边。

或者试下以下代码:

CREATE QUERY test(
VERTEX<User> source,
INT step = 3) FOR GRAPH GraphName { 
  OrAccum @visited_1;
  OrAccum @visited_2;
  SetAccum<EDGE> @@edgeSet;
  Users = {source};
  Users =
    SELECT s
    FROM   Users:s
    ACCUM  s.@visited_1 += True
  ;
  WHILE TRUE LIMIT step DO
    Users =
      SELECT t
      FROM   Users:s -(Friendship:e)- User:t
      WHERE  t.@visited_2 == FALSE
      ACCUM  IF t.@visited_1 == FALSE 
                OR (t.@visited_1 == TRUE 
                    AND s.@visited_1 == TRUE
                    AND getvid(t) > getvid(s))
               THEN @@edgeSet += e
             END,
             t.@visited_1 += True,
             s.@visited_2 += True
    ;
  END;
  PRINT @@edgeSet;
  PRINT @@edgeSet.size();
}

Schema为
image