Гремлин (Нептун) несколько сложный запрос не показывает свойства ребер

#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 с графиком, который вы создали выше, и у меня не было проблем с возвратом объектов, связанных с группой или пользователем. Если бы вы могли добавить сценарий создания, который вы используете, это было бы полезно при отладке этой проблемы