2016-12-21 20 views
1

我的设置:有确切的边缘寻找匹配的顶点通过遍历儿童

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

我的数据库:

每个人都有一定的偏爱顶点(通过描述了相对于该偏好标记的边缘连接)。所有偏好然后连接到核心概念顶点。

问题我试图解决:

我试图找到一种方法(荣誉如果作为一个小鬼查询一样简单),以一个人的顶点开始,向下遍历所有的人通过核心概念获得相同的喜好。

下面是一个配套案例的例子。在人A开始时,人员B将返回一系列完美匹配的人物。我忘了在这张图片上绘制指向这些边缘的路线:/查看不匹配的案例以查看路线。

Matching Case

下面是一个非匹配情况的例子。 B人不会被列入完美匹配列表中。为什么?因为人物B上的所有传出边缘都不能解析为在人物A上完全匹配的边缘;在这种情况下,A人拒绝吃苹果,但B人并没有对他们拒绝进食的任何东西列出类似的偏好。

Non matching case

另一个非匹配情况下,从上面的例子:如果人A拒绝吃苹果和个人B拒绝进食香蕉 - 它们将不匹配。

如果B人喜欢炸薯条并且最少喜欢芝士汉堡,那么这也是一种不匹配的情况。

我最初的想法(即我不知道如何实现)与查询

  1. 我就开始在人员A
  2. 找到所有出边喜好顶点和存储某种“标记”或映射到具有边缘标签的该首选顶点。
  3. 遍历所有类似标记边缘的顶点。将这些标记从首选顶点复制到概念顶点。
  4. 逆向而行:概念顶点 - >首选项顶点(复制厂商从概念到顶点的偏好)
  5. ...然后所有的边缘某种方式匹配到这些标记...
  6. 排除一个人从结果

任何想法?

+0

仍在研究...也许一个匹配步骤可以工作?需要做一些实验。 – Mike

+0

苹果没有'similarTo'边缘。这是否意味着它总是可选的? –

回答

2

让我们开始创建你的样品图中:

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() 

...某乙不再是比赛:

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顶点(该1或多个)的数量。

select("m").unfold(). 

展开的人专柜,所以按键会的人顶点和值将是它做出这个顶点traversers的数量。

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

最终越过category顶点的数量必须在person顶点traversers的数量相匹配。如果是这样的话,我们有一场比赛。

注意,它是需要有一个similar边缘入射到Apples顶点。

+0

这很美。这正是我正在寻找的!是的,苹果将有一个类似的边缘 - 只是跑出房间/忘了添加。谢谢! – Mike