在 gremlin 中,如何查找和排序给定顶点所属的所有连接顶点的三元组?
In gremlin, how to find and sort all triads of connected vertices that a given vertex belongs to?
我正在制作一个社交应用程序,用户可以在这里成为朋友。
对于给定的用户 A
,我想找到满足 A -isFriends-> B AND B -isFriends-> C AND C -isFriends-> A
.
的所有用户三元组
我目前的做法是:
g.V(A).repeat(__.out('isFriends')).times(3).path().by(id).toList()
然后在 gremlin 之外,我过滤掉第一个对象与最后一个对象不同的所有 Path 对象。我更希望让 gremlin 为我执行此过滤,但我不确定如何根据 path()
.
的输出进行过滤
我试过 cyclicPath()
,但这只是 returns 顶点对象的平面列表,我不明白。由此我希望输出与 path()
类似,但只包含第一个和最后一个顶点相同的路径。如果这个期望不正确,请告诉我。
然后我还想根据子遍历的结果(三个顶点有多少共同朋友)对这些路径进行排序,但我不确定如何 运行 从path()
的输出中包含的顶点,无需启动新的 gremlin 查询。
我正在使用 javascript-gremlin 驱动程序 (v3.4.4) 并针对 AWS Neptune 进行查询,其中 lambda 不可用。
如果我的方法或理解有误,请告诉我。
所以我尝试为您的问题创建一个示例图表:
sample graph
您正在尝试寻找一条简单的循环路径,我认为您可以通过以下方式实现:
g.V().hasLabel('A').as('a')
.both('isFriends').as('b')
.both('isFriends').as('c')
.where(both('isFriends').hasLabel('A'))
.select('a', 'b', 'c')
注意:三元组是对称的,因此每个元组都会 return 两次。
下面的查询可以回答您的两个问题。 优化 到 运行 只有 2 个跃点:
g.V().hasLabel("A").as("A").both("isFriends").as("B").aggregate("friends")
.out("isFriends").as("C").where(within("friends"))
.project("triad","mutual")
.by(select("A","B","C").by(label()))
.by(select("B","C").select(values).unfold()
.both("isFriends").where(within("friends"))
.groupCount().by().unfold()
.where(select(values).is(eq(2)))
.select(keys).label().fold())
.order().by(select("mutual").count(local), desc)
一些解释:
- 找到 A 朋友并将他们存储为 'friends'。
- 然后找到他们在 'friends' 内的朋友,从而与 A 成为朋友(这次使用
out
以防止重复)。
- 使用项目使结果更详细。
- 选择A、B、C得到三合会。
现在开始寻找黑社会共同朋友的有趣部分:
- 从B和C开始,找到他们也是A朋友的朋友。
- 对那些朋友进行分组计数,并仅过滤那些计数为 2 的朋友(同时拥有 B 和 C 的朋友)。
- 最后,根据共同好友的数量对结果进行排序。
代替实际的共同好友列表,您可以通过替换最后两行只保留他们的数量:
.select(keys).label().fold())
.order().by(select("mutual").count(local), desc)
与:
.count())
.order().by(select("mutual"), desc)
最后,如果您只想要三元组(仍然排序),您可以删除项目:
g.V().hasLabel("A").as("A").both("isFriends").as("B").aggregate("friends")
.out("isFriends").as("C").where(within("friends"))
.order().by(
select("B","C").select(values).unfold()
.both("isFriends").where(within("friends"))
.groupCount().by().unfold().where(select(values).is(eq(2)))
.count(), desc)
.select("A","B","C").by(label()).select(values)
我正在制作一个社交应用程序,用户可以在这里成为朋友。
对于给定的用户 A
,我想找到满足 A -isFriends-> B AND B -isFriends-> C AND C -isFriends-> A
.
我目前的做法是:
g.V(A).repeat(__.out('isFriends')).times(3).path().by(id).toList()
然后在 gremlin 之外,我过滤掉第一个对象与最后一个对象不同的所有 Path 对象。我更希望让 gremlin 为我执行此过滤,但我不确定如何根据 path()
.
我试过 cyclicPath()
,但这只是 returns 顶点对象的平面列表,我不明白。由此我希望输出与 path()
类似,但只包含第一个和最后一个顶点相同的路径。如果这个期望不正确,请告诉我。
然后我还想根据子遍历的结果(三个顶点有多少共同朋友)对这些路径进行排序,但我不确定如何 运行 从path()
的输出中包含的顶点,无需启动新的 gremlin 查询。
我正在使用 javascript-gremlin 驱动程序 (v3.4.4) 并针对 AWS Neptune 进行查询,其中 lambda 不可用。
如果我的方法或理解有误,请告诉我。
所以我尝试为您的问题创建一个示例图表: sample graph
您正在尝试寻找一条简单的循环路径,我认为您可以通过以下方式实现:
g.V().hasLabel('A').as('a')
.both('isFriends').as('b')
.both('isFriends').as('c')
.where(both('isFriends').hasLabel('A'))
.select('a', 'b', 'c')
注意:三元组是对称的,因此每个元组都会 return 两次。
下面的查询可以回答您的两个问题。 优化 到 运行 只有 2 个跃点:
g.V().hasLabel("A").as("A").both("isFriends").as("B").aggregate("friends")
.out("isFriends").as("C").where(within("friends"))
.project("triad","mutual")
.by(select("A","B","C").by(label()))
.by(select("B","C").select(values).unfold()
.both("isFriends").where(within("friends"))
.groupCount().by().unfold()
.where(select(values).is(eq(2)))
.select(keys).label().fold())
.order().by(select("mutual").count(local), desc)
一些解释:
- 找到 A 朋友并将他们存储为 'friends'。
- 然后找到他们在 'friends' 内的朋友,从而与 A 成为朋友(这次使用
out
以防止重复)。 - 使用项目使结果更详细。
- 选择A、B、C得到三合会。
现在开始寻找黑社会共同朋友的有趣部分:
- 从B和C开始,找到他们也是A朋友的朋友。
- 对那些朋友进行分组计数,并仅过滤那些计数为 2 的朋友(同时拥有 B 和 C 的朋友)。
- 最后,根据共同好友的数量对结果进行排序。
代替实际的共同好友列表,您可以通过替换最后两行只保留他们的数量:
.select(keys).label().fold())
.order().by(select("mutual").count(local), desc)
与:
.count())
.order().by(select("mutual"), desc)
最后,如果您只想要三元组(仍然排序),您可以删除项目:
g.V().hasLabel("A").as("A").both("isFriends").as("B").aggregate("friends")
.out("isFriends").as("C").where(within("friends"))
.order().by(
select("B","C").select(values).unfold()
.both("isFriends").where(within("friends"))
.groupCount().by().unfold().where(select(values).is(eq(2)))
.count(), desc)
.select("A","B","C").by(label()).select(values)