Gremlin python — как игнорировать свойство типа List при добавлении свойств в вершину

#python #gremlin #tinkerpop

#python #gremlin #tinkerpop

Вопрос:

Я хочу добавить людей в качестве вершин в графе, который работает со следующим кодом:

 from gremlin_python.process.graph_traversal import __
from gremlin_python.process.traversal import Column

persons = [{"id":1,"name":"bob","age":25}, {"id":2,"name":"joe","age":25,"occupation":"lawyer"}]    

g.inject(persons).unfold().as_('entity').
    addV('entity').as_('v').
        sideEffect(__.select('entity').unfold().as_('kv').select('v').
                   property(__.select('kv').by(Column.keys),
                            __.select('kv').by(Column.values)
                            )
                  ).iterate()
 

Вопрос 1:
Что делать, если одно из свойств является списком или dict . Пример:

 persons = [{"id":1,"name":"bob","age":25, "house":{"a":1,"b":4}}, {"id":2,"name":"joe","age":25,"occupation":"lawyer","house":{"a":1,"b":4}}]
 

Как мне игнорировать это свойство 1 (house), но при этом добавлять остальные в вершину person? Затем возьмите house и создайте другую вершину (добавьте свойства a и b) с ребром для person?

Вопрос 2. Что делать, если я хочу изменить атрибут, прежде чем добавлять его в качестве свойства в график? Например: преобразовать идентификатор в строку, а затем добавить его как свойство

Ответ №1:

Я могу ошибаться, но я чувствую, что ваш вопрос окажется более сложным, чем вы его опубликовали. Имея это в виду, я предложу ответ, который работает, учитывая предположение, что каждый дом уникален, что я прояснил с помощью «hid» (идентификатор дома), который я добавил к данным.

 gremlin> persons = [["pid":1,"name":"bob","age":25, "house":["hid":10,"a":1,"b":4]], 
......1>            ["pid":2,"name":"joe","age":25,"occupation":"lawyer","house":["hid":20,"a":1,"b":4]]]
==>[pid:1,name:bob,age:25,house:[hid:10,a:1,b:4]]
==>[pid:2,name:joe,age:25,occupation:lawyer,house:[hid:20,a:1,b:4]]
gremlin> g.inject(persons).unfold().as('entity').
......1>   addV('entity').as('v').
......2>   sideEffect(select('entity').unfold().as('kv').select('v').
......3>              choose(select('kv').by(keys).is('house'),
......4>                     addV('house').as('h').
......5>                     addE('owns').from('v').
......6>                     select('kv').by(values).unfold().as('hkv').select('h').
......7>                     property(select('hkv').by(keys),
......8>                              select('hkv').by(values)),
......9>                     property(select('kv').by(keys),
.....10>                              select('kv').by(values))))
==>v[0]
==>v[9]
gremlin> g.V().elementMap()
==>[id:0,label:entity,name:bob,pid:1,age:25]
==>[id:4,label:house,a:1,hid:10,b:4]
==>[id:9,label:entity,occupation:lawyer,name:joe,pid:2,age:25]
==>[id:14,label:house,a:1,hid:20,b:4]
gremlin> g.E().elementMap()
==>[id:5,label:owns,IN:[id:4,label:house],OUT:[id:0,label:entity]]
==>[id:15,label:owns,IN:[id:14,label:house],OUT:[id:9,label:entity]]
 

Я на самом деле не сделал здесь ничего нового, в том смысле, что я в основном просто встроил шаблон обхода, который вы уже использовали внутри себя. Обратите внимание, что в строке 6 я просто повторяю то, что было сделано в строке 2 в sideEffect() .

Теперь, если мое предположение о наличии уникальных домов в ваших данных было неверным, тогда все усложняется, потому что вы не можете легко встроить шаблоны обхода upsert в этом контексте. Upserts обычно включают шаблон fold / coalesce / unfold, который немедленно конфликтует с этим шаблоном «только вставка», который вы используете, поскольку вы не можете вернуться назад при обходе (т. Е. Обратитесь к Предыдущему шагу), который находится за уменьшающим барьером (т. Е. fold). Я думаю, что в этом случае я бы попытался реструктурировать исходные данные, чтобы сделать их более удобными для чистых вставок, а не операций upsert.

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

1. Это в некоторой степени помогает мне. Но да, у нас нет уникальных идентификаторов для каждого дома. Кроме того, у нас есть несколько атрибутов с типом list / dict . Можем ли мы в любом случае игнорировать эти атрибуты? Например: select(‘v’).choose( указывать / перечислять атрибуты , игнорировать , добавлять другие свойства )

2. конечно .. я сделал is('house') , но вы могли бы указать любой предикат, который вы действительно хотите. is(within('house','car')) например, если вы хотите предоставить несколько свойств, но посмотрите на choose() step — он обладает большой гибкостью для операторов стиля case / switch: tinkerpop.apache.org/docs/current/reference/#choose-step

3. Это идеально. Спасибо. Наконец, есть ли какой-нибудь способ вместо указания имен атрибутов просто указать тип данных атрибута? Потому что источник может иметь разные атрибуты этого типа. выберите (‘v’).выберите(атрибуты типа dict / list, игнорировать, добавить другие свойства)

4. нет — в настоящее время у Gremlin нет методов для обработки типа данных. надеюсь, в будущем, хотя, поскольку это обычный запрос.

5. Хорошо, спасибо. Быстрый вопрос, при добавлении свойств в приведенный выше код: .property(select('kv').by(Column.keys),select('kv').by(Column.values)) как мы заботимся о свойствах null?