Как фильтровать связанные объекты с помощью Gremlin Cosmos DB?

#.net #gremlin #azure-cosmosdb-gremlinapi #gremlinnet

#.net #gremlin #azure-cosmosdb-gremlinapi #gremlinnet

Вопрос:

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

 [[user: [USEROBJECT], usersThatAreNotFriends: [[USEROBJECT]...]]...]
  

Я использую конечную точку Cosmos DB Gremlin и испытываю трудности с фильтрацией / объединением пользователей, которые уже связаны, и всех пользователей.

Моя идея заключалась:

 g.V().hasLabel('user').as('user').flatMap(g.V().hasLabel('user').where(__.eq(select('user').out('isFriend')).fold()).as('usersThatAreNotFriends').select('user', 'usersThatAreNotFriends')
  

Для настройки моего примера используйте:

 g.addV('user').property('id','user_1').property('partition_key','1')
g.addV('user').property('id','user_2').property('partition_key','2')
g.addV('user').property('id','user_3').property('partition_key','3')
g.addV('user').property('id','user_4').property('partition_key','4')
g.V('user_1').addE('has_relation').to(g.V('user_2'))
g.V('user_2').addE('has_relation').to(g.V('user_1'))
g.V('user_2').addE('has_relation').to(g.V('user_4'))
g.V('user_4').addE('has_relation').to(g.V('user_2'))
  

Ожидаемый результат должен быть представлен простым способом:

 [user_1: [user_3, user_4], user_2:[user_3], 
user_3:[user_1, user_2, user_3], user_4:[user_1, user_3]]
  

Комментарии:

1. Было бы полезно, если бы вы могли добавить небольшой набор addV и addE шагов, которые строят примерный график, представляющий ваши данные.

Ответ №1:

Я изменил ваш запрос, чтобы добавить идентификаторы как реальные идентификаторы

 g.addV('user').property(id,'user_1').property('partition_key','1')
g.addV('user').property(id,'user_2').property('partition_key','2')
g.addV('user').property(id,'user_3').property('partition_key','3')
g.addV('user').property(id,'user_4').property('partition_key','4')
g.V('user_1').addE('has_relation').to(g.V('user_2'))
g.V('user_2').addE('has_relation').to(g.V('user_1'))
g.V('user_2').addE('has_relation').to(g.V('user_4'))
g.V('user_4').addE('has_relation').to(g.V('user_2'))   
  

В вашем примере иногда вы показывали одного и того же человека в результате, поэтому я предлагаю два разных запроса. В первом случае человек не дружит с самим собой.

 gremlin> g.V().as('p').
......1>    project('person','not-friends').
......2>      by().
......3>      by(V().where(__.not(__.in('has_relation').as('p'))).fold())
==>[person:v[user_3],not-friends:[v[user_3],v[user_2],v[user_1],v[user_4]]]
==>[person:v[user_2],not-friends:[v[user_3],v[user_2]]]
==>[person:v[user_1],not-friends:[v[user_3],v[user_1],v[user_4]]]
==>[person:v[user_4],not-friends:[v[user_3],v[user_1],v[user_4]]] 
  

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

 gremlin>  g.V().as('p').
......1>    project('person','not-friends').
......2>      by().
......3>     by(V().where(__.not(__.in('has_relation').as('p')).where(neq('p'))).fold())
==>[person:v[user_3],not-friends:[v[user_2],v[user_1],v[user_4]]]
==>[person:v[user_2],not-friends:[v[user_3]]]
==>[person:v[user_1],not-friends:[v[user_3],v[user_4]]]
==>[person:v[user_4],not-friends:[v[user_3],v[user_1]]]
  

В качестве дополнительного примечания, чтобы узнать, кто из людей является друзьями, вы можете использовать простой group().by() подход.

 gremlin> g.V().aggregate('all').group().by().by(out().fold()).unfold()
==>v[user_3]=[]
==>v[user_2]=[v[user_1], v[user_4]]
==>v[user_1]=[v[user_2]]
==>v[user_4]=[v[user_2]]    
  

Комментарии:

1. Проблема в том, что вы не можете использовать простой символ V в Azure Cosmos DB: ExceptionType: GraphCompileException ExceptionMessage: Ошибка компиляции запроса Gremlin: не удается разрешить символ ‘V’ в текущем контексте. @ строка 1, столбец 56. Источник ошибок 1: Microsoft. Azure. Космос. Гремлин. Основной запрос Gremlin: a69f7871-2ae5-4645-91f0-0cb7af165601 Контекст : область графических вычислений: graphparse-translate-validatesymbolresolution GraphInterOpStatusCode: QuerySyntaxError HResult : 0x80131500 Введите ‘:help’ или ‘:h’ для получения справки.

2. Хорошо, использование промежуточного обхода V() довольно распространено, поэтому это казалось естественным способом решения этой проблемы. Я добавил способ задать обратный вопрос, который просто использует группу. Возможно, используйте это и в своем приложении сделайте все остальное. Как только позволит время, я попытаюсь добавить альтернативную форму.

3. Большое вам спасибо за ваш быстрый ответ. Надеюсь, Cosmos DB скоро получит лучшую поддержку всего Gremlin API…