CosmosDB Gremlin: использование сохраненного значения в последующем фильтре
У меня проблема при попытке фильтрации на основе сохраненного списка строк. Я хочу построить этот список в sideEffect()
а затем использовать его в последующем where(without())
, Я ожидаю список пользователей, исключая user.a1
в следующем примере, но user.a1
Включено.
g.V().hasLabel('user').sideEffect(hasId('user.a1').id().store('exclude')).where(id().is(without('exclude')))
[
{
"id": "user.a1",
"label": "user",
"type": "vertex"
},
{
"id": "user.b1",
"label": "user",
"type": "vertex"
},
...
]
Я предполагаю, что это происходит, потому что Гремлин проверяет литеральную строку exclude
так, как мне заставить это проверить идентификаторы, хранящиеся в exclude
переменная вместо?
Например, это работает:
g.V().hasLabel('user').sideEffect(hasId('user.a1').id().store('exclude')).where(id().is(without('user.a1')))
[
{
"id": "user.b1",
"label": "user",
"type": "vertex"
},
...
]
РЕДАКТИРОВАТЬ #1
Пробовал вопросы, предложенные stephen mallette, но все еще не получил именно то, что я ищу (может быть, это невозможно на CosmosDB?).
Прежде всего, по-видимому filter
недоступна на CosmosDB:
g.V().hasLabel('user').
sideEffect(hasId('user.a1').id().store('exclude')).
filter(id().where(without('exclude')))
ExceptionType : GraphCompileException
ExceptionMessage : Gremlin Query Compilation
Error: Unable to find any method 'filter' @ line 1, column 81. 1
Error(s) Source : Microsoft.Azure.Graphs
Второе предложение привело к пустому набору, а второе сработало:
g.V().hasLabel('user').hasId('user.a1').
aggregate('exclude').where(without('exclude'))
[]
g.V().hasLabel('user').
sideEffect(hasId('user.a1').aggregate('exclude')).
where(without('exclude'))
[
{
"id": "user.b1",
"label": "user",
"type": "vertex"
},
{
"id": "user.b2",
"label": "user",
"type": "vertex"
},
...
]
Проблема в том, что я хочу фильтровать ребра, используя значения их свойств. Моя реальная ситуация такова, что я хочу объединить следующие два запроса в один, если это возможно: получить набор role
идентификаторы вершин, а затем получить пользователей, которые играют одну из ролей и принадлежат к подгруппе групп.
(Пользователи принадлежат к группе с идентификатором роли в этой группе, установленным как свойство пользователя-> группа belongs_to
край.)
- Получить набор ролей из иерархии ролей (
role.2
+ все родители)
g.V('role.2').store('roles').
repeat(__.out('is_under')).emit().store('roles').
select('roles').unfold().dedup().id()
[
"role.2",
"role.1"
]
- Получите пользователей с вышеуказанными ролями в группе B или выше и дайте им преимущество в другой роли.
g.V('group.B').
sideEffect(inE('belongs_to').
has('role',within('role.1','role.2')).outV().store('users')).
repeat(__.out('belongs_to')).emit().inE('belongs_to').
has('role',within('role.1','role.2')).outV().store('users').
select('users').unfold().addE('has').to(g.V('role.12'))
1 ответ
Вот один из способов сделать это:
g.V().hasLabel('user').
sideEffect(hasId('user.a1').id().store('exclude')).
filter(id().where(without('exclude')))
Есть несколько вещей, которые вы можете изменить в зависимости от того, насколько этот пример, который вы создали, соответствует вашим реальным потребностям или был упрощен из-за вашего вопроса. Во-первых, вы можете, вероятно, отложить sideEffect()
так как store()
сам по себе является технически побочным эффектом. Во-вторых, интересно, если вы действительно хотите store()
там нет aggregate()
- где агрегат будет жадно собирать все идентификаторы, прежде чем перейти к фильтрации:
g.V().hasLabel('user').
hasId('user.a1').aggregate('exclude').by(id).
filter(id().where(without('exclude')))
Это, конечно, небольшой обход "ничего не делать", так как вы уже отфильтровали вершины, которые вам не нужны hasId('user.a1')
, но, опять же, я предполагаю, что у вас есть более сложный запрос, чем тот, который вы продемонстрировали. Я просто указываю на механику Гремлин.
Вы также можете упростить дальнейшее упрощение, если не беспокоитесь об идентификаторах - равенство вершин будет таким же, как у идентификатора, и, следовательно, следующее будет эквивалентно приведенному выше с меньшим количеством шагов Gremlin:
g.V().hasLabel('user').
hasId('user.a1').aggregate('exclude').
where(without('exclude'))
Задавая вопросы о Gremlin, лучше всего добавить сценарий, который генерирует примеры данных, чтобы вы могли получить проверенный обход, соответствующий вашим потребностям. Вместо этого я изменил "современный" график, добавив метку "weight":
gremlin> g.addV('weight').property('v',1.0d)
==>v[13]
где значение "v" соответствует двум значениям веса для существующих ребер игрушечного графа. Без filter()
Я думаю, что вы попадаете в такую схему:
gremlin> g.V().hasLabel('weight').
......1> aggregate('w').by('v').
......2> V().hasLabel('person').
......3> outE().as('x').values('weight').
......4> where(within('w')).
......5> select('x')
==>e[8][1-knows->4]
==>e[10][4-created->5]