【问题标题】:Finding vertices with exact edge matches traversing through children查找具有精确边匹配的顶点,遍历子节点
【发布时间】:2017-05-07 12:29:00
【问题描述】:

我的设置:

我将 OrientDB 与大型人物顶点图一起使用。我正在使用 gremlin java 驱动程序来访问这个数据库,因为我想最终切换到不同的图形数据库。

我的数据库:

每个人都有特定的偏好顶点(通过描述该偏好关系的标记边连接)。然后所有偏好都连接到核心概念顶点。

我要解决的问题:

我正在尝试找到一种方法(如果它像 Gremlin 查询一样简单,则值得称赞)从 Person 顶点开始,并通过核心概念遍历所有具有相同偏好的人。

这是一个匹配案例的虚构示例。当从人 A 开始时,人 B 将在完美匹配的人列表中返回。我忘了在这张图片上画出这些边缘的方向:/ 看看不匹配的情况以查看方向。

这是一个不匹配的例子。人 B 不会在人的完美匹配列表中返回。为什么?因为人 B 上的所有出边都不会解析为人 A 上相同匹配的边;在这种情况下,A 拒绝吃苹果,但 B 没有列出他们拒绝吃的任何东西的类似偏好。

上例中的另一个不匹配情况:如果 A 拒绝吃苹果而 B 拒绝吃香蕉——它们将不匹配。

如果 B 最喜欢 Fries 而最不喜欢 Cheeseburgers,这也是不匹配的情况。

我最初的想法(我不确定如何实现)使用查询

  1. 我会从 A 人开始
  2. 查找到偏好顶点的所有传出边,并存储某种“标记”或映射到带有边标签的偏好顶点。
  3. 从这些顶点向下遍历所有 SimilarTo 标记的边。将这些标记从偏好顶点复制到概念顶点。
  4. 反转线:概念顶点 -> 偏好顶点(从概念到偏好顶点的复制制作者)
  5. ...然后以某种方式将所有边缘与这些标记匹配...
  6. 从结果中排除人员 a

有什么想法吗?

【问题讨论】:

  • 仍在研究...也许匹配步骤可以工作?需要做一些实验。
  • 苹果没有similarTo 边。这是否意味着它始终是可选的?

标签: orientdb graph-databases tinkerpop tinkerpop3


【解决方案1】:

让我们从创建示例图开始:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("person").property("name", "Person A").as("pa").
......1>   addV("person").property("name", "Person B").as("pb").
......2>   addV("food").property("name", "Hamburgers").as("hb").
......3>   addV("food").property("name", "Chips").as("c").
......4>   addV("food").property("name", "Cheeseburgers").as("cb").
......5>   addV("food").property("name", "Fries").as("f").
......6>   addV("category").property("name", "Burgers").as("b").
......7>   addV("category").property("name", "Appetizers").as("a").
......8>   addE("most").from("pa").to("hb").
......9>   addE("most").from("pb").to("cb").
.....10>   addE("least").from("pa").to("c").
.....11>   addE("least").from("pb").to("f").
.....12>   addE("similar").from("hb").to("b").
.....13>   addE("similar").from("cb").to("b").
.....14>   addE("similar").from("c").to("a").
.....15>   addE("similar").from("f").to("a").iterate()

您正在寻找的查询如下(我将在后面解释每个步骤):

gremlin> g.V().has("person", "name", "Person A").as("p").
......1>   outE("most","least","refuses").as("e").inV().out("similar").
......2>   store("x").by(constant(1)).
......3>   in("similar").inE().where(eq("e")).by(label).outV().where(neq("p")).
......4>   groupCount().as("m").
......5>   select("x").by(count(local)).as("c").
......6>   select("m").unfold().
......7>   where(select(values).as("c")).select(keys).values("name")
==>Person B

现在,当我们添加“拒绝吃苹果”关系时:

gremlin> g.V().has("person", "name", "Person A").as("p").
......1>   addV("food").property("name", "Apples").as("a").
......2>   addV("category").property("name", "Fruits").as("f").
......3>   addE("refuses").from("p").to("a").
......4>   addE("similar").from("a").to("f").iterate()

...B 不再匹配:

gremlin> g.V().has("person", "name", "Person A").as("p").
......1>   outE("most","least","refuses").as("e").inV().out("similar").
......2>   store("x").by(constant(1)).
......3>   in("similar").inE().where(eq("e")).by(label).outV().where(neq("p")).
......4>   groupCount().as("m").
......5>   select("x").by(count(local)).as("c").
......6>   select("m").unfold().
......7>   where(select(values).as("c")).select(keys).values("name")
gremlin>

让我们一步一步/一行一行的看一遍查询:

g.V().has("person", "name", "Person A").as("p").

这应该很清楚:从人 A 开始。

outE("most","least","refuses").as("e").inV().out("similar").

遍历出边并设置一个标记,以便我们以后可以参考这些边。然后遍历到我称之为category的顶点。

store("x").by(constant(1)).

为每个category 顶点添加一个1 到内部集合。您也可以存储顶点本身,但这会浪费内存,因为我们不需要来自顶点的任何信息。

in("similar").inE().where(eq("e")).by(label).outV().where(neq("p")).

沿similar 边缘向另一个方向移动到food,然后沿与标记边缘具有相同标签的那些边缘从头开始。最后忽略遍历开始的人(人A)。

groupCount().as("m").

计算到达每个人顶点的遍历器数量。

select("x").by(count(local)).as("c").

计算Category 顶点的数量(1s)。

select("m").unfold().

展开人员计数器,因此键将是人员顶点,值将是到达此顶点的遍历器的数量。

where(select(values).as("c")).select(keys).values("name")

最终,交叉的category 顶点的数量必须与person 顶点上的遍历器数量相匹配。如果是这样,我们就有了比赛。

注意,similar 边缘必须与 Apples 顶点发生事件。

【讨论】:

  • 这很漂亮。这正是我正在寻找的!是的,苹果也有类似的优势——只是空间不足/忘记添加了。谢谢!
猜你喜欢
  • 2021-10-25
  • 1970-01-01
  • 2013-07-20
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 2020-07-07
相关资源
最近更新 更多