点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为