Что-то показалось неправильным в ваших данных, учитывая ожидаемый результат, поэтому мне пришлось внести исправления:
- Вершина 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, которые также ускорят поиск ребер по «баллу» (не уверен, что это сильно поможет при «принятии решения», поскольку у него низкая селективность).