Правильный способ обновления Edges in Bulbs (neo4j или titan)

Я экспериментирую с Bulbs для взаимодействия с графовой базой данных. (Производство будет использовать Titan, локально Neo4j кажется лучшим для экспериментов).

У меня в голове не укладывается это понятие...

Bulbs показывает, как создавать новые вершины...

>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> g.edges.create(james, "knows", julie)

Копаясь в документах, я также могу заменить это на «получить или создать»:

>>> james = g.vertices.get_or_create('name',"James",{'name':'james')

Чего я не могу понять, так это того, как получить существующий Edge. Мои попытки до сих пор заканчивались воссозданием десятков отношений «Джеймс знает Джули» вместо доступа к существующему для обновления.

Может ли кто-нибудь указать мне в правильном направлении?


person Jonathan Vanasco    schedule 19.08.2013    source источник


Ответы (1)


Вы можете добавлять/обновлять свойства ребра, но с графовыми базами данных вы не можете обновлять атрибуты, которые делают его ребром, т. е. вы не можете обновлять его входящие и исходящие идентификаторы вершин или метки. Вместо этого вы удаляете край и добавляете новый.

Вот различные способы получения края и обновления его свойств.

Получить ребро можно по его ID:

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> edge = g.edges.create(james, "knows", julie)
>>> edge2 = g.edges.get(edge.eid)       # get the edge again
>>> assert edge == edge2
>>> edge2.someprop = "somevalue"
>>> edge2.save()

Вы можете найти ребро по его свойствам, если они есть и они проиндексированы:

# will return an iterator or None edges (may return more than one)
>>> edges = g.edges.index.lookup(someprop="somevalue") 
>>> edge = edges.next()
>>> edge.someprop = "newvalue"
>>> edge.save()

# will return 1 or None edges (or an error if more than 1 edge found)
>>> edge = g.edges.index.get_unique(someprop="somevalue") 
>>> edge.someprop = "newvalue"
>>> edge.save()

Вы также можете получить преимущество, используя Gremlin, пройдя его вершины:

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> script = "g.V('name',name1).outE(label).as('e').inV.has('name',name2).back('e')"
>>> params = dict(name1="James", label="knows", name2="Julie")
>>> edges = g.gremlin.query(script, params)
>>> edge = edges.next()
>>> edge.someprop = "newvalue"
>>> edge.save()

См. паттерн обратного хода гремлина...

Но самый эффективный способ обновить ребро, когда вы не знаете его идентификатор, — это обновить ребро с помощью скрипта Gremlin, который ищет его (таким образом у вас будет только один круговой путь к серверу, а не два):

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> script = "g.V('name',name1).outE(label).as('e').inV.has('name',name2).back('e').sideEffect{it.someprop = someprop}"
>>> params = dict(name1="James", label="knows", name2="Julie", someprop="somevalue")
>>> edges = g.gremlin.query(script, params)
>>> edge = edges.next()
>>> edge.someprop
'somevalue'

См. https://github.com/tinkerpop/gremlin/wiki/Updating-a-Graph

И для удобочитаемости, вместо того, чтобы писать однострочники Gremlin в Python REPL, я бы поместил свои скрипты Gremlin в файл gremlin.groovy, как показано здесь:

http://bulbflow.com/docs/api/bulbs/groovy/

Вот реальный пример использования Gremlin для получения или создания преимущества:

https://github.com/espeed/lightbulb/blob/master/lightbulb/gremlin.groovy#L88

И подробное объяснение кода здесь:

Есть ли эквивалент фиксации в каркасе лампочки для neo4j

person espeed    schedule 25.08.2013
comment
Спасибо. Похоже, что neo4j представил g.edges.get_or_create в новой версии. Не уверен, что другие серверы следуют. Мне придется поиграть с вашими подходами. Мы конвертируем некоторые системы СУБД в графы, и есть много пакетной работы, когда мы, возможно, уже создали ребро и хотим его обновить, а не создавать его повторно с меньшим объемом данных. - person Jonathan Vanasco; 04.09.2013
comment
Для пакетных обновлений обычно используют Redis или карту атрибутов Java/Groovy в памяти для идентификаторов вершин/ребер. В зависимости от того, как вы предварительно обрабатываете свои данные, может иметь смысл использовать Redis из Python, но может быть более эффективно использовать Redis из Java через клиент jedis. См. мой пост в Группе пользователей Gremlin, сделанный несколько лет назад: Пусть Gremlin общается с Redis в режиме реального времени, пока он движется по графику (groups.google.com/d/topic/gremlin-users/xhqP-0wIg5s/discussion) — возможно, вам потребуется обновить код для работы с последняя версия Гремлина. - person espeed; 08.09.2013