#javascript #gremlin #amazon-neptune
#javascript #гремлин #amazon-нептун
Вопрос:
У меня есть набор данных в моей базе данных (AWS Neptune), и я запрашиваю его с помощью Gremlin (NodeJS).
Данные выглядят так, и у меня есть запрос, который выглядит следующим образом:
g.V().hasLabel('group').inE('belongs_to')
.outV().has('user_id', user_id).outE()
.otherV().inE().hasLabel('shared_with')
.outV().has('type', type).aggregate('object_id').fold()
.V().hasLabel('user').has('user_id', user_id).inE().hasLabel('shared_with')
.outV().has('type', type).aggregate('object_id').cap('object_id')
.unfold().dedup().valueMap().toList();
В итоге я получаю (что правильно) список объектов и с кем они совместно используются, «кем» может быть пользователь или группа.
Итак, это было хорошее начало (мне потребовалось некоторое время, чтобы понять это, и я ухватил основную идею из StackOverflow), но я не понимаю свойств ребер.
Изначально у меня было два отдельных запроса: один для объектов, совместно используемых группами, и один для объектов, совместно используемых пользователями. Это сработало нормально, но, очевидно, заняло больше времени, и мне пришлось повторно согласовать два списка, которые я получал.
Я попытался изменить свой запрос, поместив as(‘x’) за ребрами и вершинами, которые мне нужны, но тогда select вообще ничего не возвращал. Без select() as() игнорируется, и я получу те же данные, что и раньше.
Сначала я пробовал с помощью .local(__.union()) но это тоже не сработало. Я запустил Gremlin / Neptune на прошлой неделе, и хотя я добился приличного прогресса, я могу использовать только несколько простых запросов: (
Обновить:
Вот как я создаю группы:
let group = await g.addV('group')
.property('group_id', group_id)
.property('name', name)
.property('type', groupType)
.property('owner', owner)
.next();
//group_id and owner are UUID.
Как добавить пользователя в группу:
t = await g.addV('user')
.property('user_id', user.id)
.property('name', user.name)
.next();
t = await g.V()
.has('user', 'user_id', user.id) // Find the user
.addE('belongs_to') // Add a new edge
.to(g.V().has('group', 'group_id', group_id))
// user.id is a UUID
Создание объекта:
let obj = await g.addV('object')
.property('object_id', object_id)
.property('ref', ref)
.property('type', type)
.property('owner', owner)
.property('creation_time', d.getTime().toString())
.next();
Совместное использование с пользователем или группой:
t = await g.V().has('object','object_id', object_id).has('owner', owner)
.addE('shared_with') // Add a new edge
.property('read', canRead)
.property('edit', canEdit)
.property('share', canShare)
.to(g.V().has('user', 'user_id', id)) // Find the user to link to
.next();
// For group: .to(g.V().has('group', 'group_id', id))
Ответ №1:
Я не был точно уверен, какие данные вы пытались вернуть, но я понял, что вы хотите ответить на вопрос «К каким объектам у этого пользователя есть доступ и каковы разрешения?»
Если это так, то лучшее место для начала обхода с вершины пользователя, из которой вы можете затем union()
передавать объекты, совместно используемые с группой, в объекты, непосредственно предоставленные пользователю. Наконец, вы можете project()
из shared_with ребер получить значения объекта, а также свойства ребер для разрешений.
g.V().has('User', 'user_id', 'A').
union(
out('belongs_to').inE('shared_with'),
inE('shared_with')
).project('object', 'permission').
by(outV().valueMap().with(WithOptions.tokens)).
by(valueMap().with(WithOptions.tokens))
Он with(WithOptions.tokens)
будет включать метаданные, такие как id
и label
, поэтому, если это не нужно, вы можете удалить это из обхода.
Комментарии:
1. Спасибо, я попробую это. Я запутался во всех разных способах создания запросов 🙂
2. Я попробовал, и, хотя он работает нормально, если объект предоставлен пользователю, как только объект предоставляется группе (к которой принадлежит пользователь), Нептун выдает: {«RequestID»:»c1de62bb-5542-46e1-9415-8bf3024f25d6″,»code»: «InternalFailureException»,»detailedMessage»: «В Нептуне произошла непредвиденная ошибка».}
3. Похоже, Нептун не слишком любит with(withOptions.tokens) …
4. Итак, оказывается, что у Нептуна возникли некоторые проблемы с with(withOptions.tokens). Я немного покопался, и withOptions.tokens преобразуется в «~tinkerpop.ValueMap.tokens». Символ ~ означает, что он скрыт. Если я использую with(«») , это работает, но я получаю лишние вещи, которые мне не нужны, и как только я передаю «~tinkerpop.ValueMap.tokens», Нептун проигрывает…
5. Я протестировал это на Neptune с графиком, который вы создали выше, и у меня не было проблем с возвратом объектов, связанных с группой или пользователем. Если бы вы могли добавить сценарий создания, который вы используете, это было бы полезно при отладке этой проблемы