#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-step3. Это идеально. Спасибо. Наконец, есть ли какой-нибудь способ вместо указания имен атрибутов просто указать тип данных атрибута? Потому что источник может иметь разные атрибуты этого типа. выберите (‘v’).выберите(атрибуты типа dict / list, игнорировать, добавить другие свойства)
4. нет — в настоящее время у Gremlin нет методов для обработки типа данных. надеюсь, в будущем, хотя, поскольку это обычный запрос.
5. Хорошо, спасибо. Быстрый вопрос, при добавлении свойств в приведенный выше код:
.property(select('kv').by(Column.keys),select('kv').by(Column.values))
как мы заботимся о свойствах null?