Gremlin - поиск связанных узлов с несколькими логическими условиями как для узлов, так и для свойств ребер - PullRequest
0 голосов
/ 05 августа 2020

Я хочу найти узлы, которые должны быть связаны с данным узлом, где ссылка определяется некоторым logi c, который использует атрибут узлов и существующих ребер со следующим logi c:

A) (У пары одинаковый zip (атрибут узла) и name_similarity (атрибут edge)> 0,3 ИЛИ

B) Пара имеет другой zip и name_similarity> 0,5 ИЛИ

C) Пара имеет тип ребра "external_info" со значением = "connect")

D) И (пара не имеет типа ребра с "external info" со значением = "disconnect" )

Короче: (A | B | C) & (~ D)

Я все еще новичок ie в гремлине, поэтому я не уверен, как я может сочетать несколько условий на ребрах и узлах.

Ниже приведен код для создания графа, а также ожидаемые результаты для этого графа:

# creating nodes

(g.addV('person').property('name', 'A').property('zip', '123').
addV('person').property('name', 'B').property('zip', '123').
addV('person').property('name', 'C').property('zip', '456').
addV('person').property('name', 'D').property('zip', '456').
addV('person').property('name', 'E').property('zip', '123').
addV('person').property('name', 'F').property('zip', '999').iterate())

node1 = g.V().has('name', 'A').next()
node2 = g.V().has('name', 'B').next()
node3 = g.V().has('name', 'C').next()
node4 = g.V().has('name', 'D').next()
node5 = g.V().has('name', 'E').next()
node6 = g.V().has('name', 'F').next()

# creating name similarity edges

g.V(node1).addE('name_similarity').from_(node1).to(node2).property('score', 1).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node3).property('score', 0.2).next() # under threshold
g.V(node1).addE('name_similarity').from_(node1).to(node4).property('score', 0.4).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node5).property('score', 1).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node6).property('score', 0).next() # under threshold

# creating external output edges

g.V(node1).addE('external_info').from_(node1).to(node5).property('decision', 'connect').next() 
g.V(node1).addE('external_info').from_(node1).to(node6).property('decision', 'disconnect').next() 

Ожидаемый результат - для входного узла A - это узлы B (из-за условия A), D (из-за условия B) и F (из-за условия C). узел E не должен быть связан из-за условия D.

Я ищу запрос Gremlin, который получит эти результаты.

1 Ответ

0 голосов
/ 07 августа 2020

Что-то показалось неправильным в ваших данных, учитывая ожидаемый результат, поэтому мне пришлось внести исправления:

  • Вершина D не отображалась в результатах, потому что «оценка» была меньше 0,5
  • края "external_info" казались перевернутыми

Вот данные, которые я использовал:

g.addV('person').property('name', 'A').property('zip', '123').
addV('person').property('name', 'B').property('zip', '123').
addV('person').property('name', 'C').property('zip', '456').
addV('person').property('name', 'D').property('zip', '456').
addV('person').property('name', 'E').property('zip', '123').
addV('person').property('name', 'F').property('zip', '999').iterate()
node1 = g.V().has('name', 'A').next()
node2 = g.V().has('name', 'B').next()
node3 = g.V().has('name', 'C').next()
node4 = g.V().has('name', 'D').next()
node5 = g.V().has('name', 'E').next()
node6 = g.V().has('name', 'F').next()
g.V(node1).addE('name_similarity').from(node1).to(node2).property('score', 1).next() 
g.V(node1).addE('name_similarity').from(node1).to(node3).property('score', 0.2).next() 
g.V(node1).addE('name_similarity').from(node1).to(node4).property('score', 0.6).next() 
g.V(node1).addE('name_similarity').from(node1).to(node5).property('score', 1).next() 
g.V(node1).addE('name_similarity').from(node1).to(node6).property('score', 0).next() 
g.V(node1).addE('external_info').from(node1).to(node6).property('decision', 'connect').next() 
g.V(node1).addE('external_info').from(node1).to(node5).property('decision', 'disconnect').next() 

Я использовал следующий подход:

gremlin> g.V().has('person','name','A').as('a').
......1>   V().as('b').
......2>   where('a',neq('b')).
......3>   or(where('a',eq('b')).                                                    // A
......4>        by('zip').
......5>      bothE('name_similarity').has('score',gt(0.3)).otherV().where(eq('a')), 
......6>      bothE('name_similarity').has('score',gt(0.5)).otherV().where(eq('a')), // B
......7>      bothE('external_info').                                                // C
......8>        has('decision','connect').otherV().where(eq('a'))).
......9>   filter(__.not(bothE('external_info').                                     // D
.....10>                 has('decision','disconnect').otherV().where(eq('a')))).
.....11>   select('a','b').
.....12>    by('name')
==>[a:A,b:B]
==>[a:A,b:D]
==>[a:A,b:F]

I думаю, что это содержит все logi c, которые вы искали, но я не тратил много времени на его оптимизацию, так как не думаю, что какая-либо оптимизация поможет обойти боль полного сканирования графика V().as('b'), поэтому либо ваша ситуация включает относительно небольшой граф (возможно, в памяти), и этот запрос будет работать, либо вам нужно будет найти другой метод вместе. Возможно, у вас есть способы еще больше ограничить "b", которые могут помочь? Если что-то в этом роде возможно, я бы, вероятно, попытался лучше определить направленность обхода краев, чтобы избежать bothE() и вместо этого ограничить outE() или inE(), что избавит от otherV(). Надеюсь, вы используете граф, который учитывает индексы вершин c, которые также ускорят поиск ребер по «баллу» (не уверен, что это сильно поможет при «принятии решения», поскольку у него низкая селективность).

...