Почему вызовы API не работают в Gremlin Python? - PullRequest
0 голосов
/ 24 сентября 2019

В gremlin-python я могу сделать:

for e in g.E().toList():
        print(e)

и получу результат как

e[11][4-created->3]
e[12][6-created->3]
e[7][1-knows->2]
e[8][1-knows->4]
e[9][1-created->3]
e[10][4-created->5]

Согласно

http://tinkerpop.apache.org/javadocs/3.4.3/core/org/apache/tinkerpop/gremlin/structure/Edge.html

Edge имеет метод доступа inVertex ().Перевод этой идеи в python приводит к:

for e in g.E().toList():
        print (e.inVertex().id)

и ошибке

AttributeError: 'Edge' object has no attribute 'inVertex'

То же самое справедливо для довольно многих других "простых" вызовов API.

for e in g.E().toList():
        print(e.property('weight'))

также дает сбой

Что это такое и как обходной путь?

Ответы [ 3 ]

2 голосов
/ 25 сентября 2019

В графе TinkerPop элементы (например, вершины, ребра, свойства вершин) часто проходят процесс «отсоединения».Обходы Gremlin, которые возвращают элементы графа из удаленных источников, проходят через этот процесс и в этих случаях обычно отсоединяются от «ссылок».Ссылка предоставляет достаточно информации для повторного присоединения к удаленному графу.Для этого процесса повторного вложения нужны только id и label.Поэтому свойства не возвращаются.Это одинаково для всех языков, которые поддерживает Gremlin, а не только для Python (хотя в последнем примечании я немного опровергну это утверждение).

Говоря конкретно о вариантах языка Gremlin, таких как Python, этиРеализации Gremlin не имеют полной виртуальной машины Gremlin для обработки обходов, и никогда не предполагалось создавать полные структуры графа на стороне Python - только графические элементы со ссылками, совпадающими с тем, что будет возвращено из удаленных источников.Это также уменьшает объем кода на стороне Python, который необходимо поддерживать, потому что TinkerPop может полагаться на стандартные примитивы, такие как Dictionary, List и т. Д., Которые существуют во всех языках программирования.

Техническая история в стороне,возвращение ссылок заставляет лучше писать Гремлин в соответствии с лучшими практиками.Пользователи должны точно указать, какие данные они хотят в своем обходе Gremlin.Вместо:

g.V().hasLabel('customer')

вы бы предпочли:

g.V().hasLabel('customer').valueMap(true,'name')

или в 3.4.4:

 g.V().hasLabel('customer').elementMap('name')

, которая возвращает менее вложенную структуру, чем valueMap(),elementMap() очень хорошо работает для ребер и является заменой более сложных подходов через project(), чтобы получить данные, которые вы запрашиваете от ребра в вашем вопросе:

gremlin> g.V().has('person','name','marko').elementMap()
==>[id:1,label:person,name:marko,age:29]
gremlin> g.V().has('person','name','marko').elementMap('name')
==>[id:1,label:person,name:marko]
gremlin> g.V().has('person','name','marko').properties('name').elementMap()
==>[id:0,key:name,value:marko]
gremlin> g.E(11).elementMap()
==>[id:11,label:created,IN:[id:3,label:software],OUT:[id:4,label:person],weight:0.4]

Это действительно не отличается в SQLгде вы, скорее всего, этого не сделаете:

SELECT * FROM customer

, но вместо этого:

SELECT name FROM customer

Возвращение ссылок и принуждение пользователей к более явному пониманию того, что они возвращают, также решает огромную проблему смульти / мета-свойства.Если пользователь возвращает вершины и непреднамеренно возвращает «толстую» вершину (например, вершину с 1 миллионом свойств), это окажет значительное влияние на сервер при попытке ее вернуть.Отсоединение от ссылки не дает лазейки для пользователей, чтобы застрять.

Все это говорит о том, что по состоянию на 3.4.3 все еще существуют точки несоответствия с отсоединением, а в некоторых случаях в Java есть другие способыэтот отряд работает за пределами справочного отряда.TinkerPop пытается полностью соответствовать этому подходу, но пытается сделать это таким образом, чтобы не нарушать существующий код в существующих строках выпуска.Вероятно, это не тот ответ, который вы ищете, но, по крайней мере, он помогает объяснить некоторые причины и историю того, почему все так, как есть.

0 голосов
/ 24 сентября 2019

toList() выполняет запрос gremlin и упаковывает результат в список.Таким образом, вы не можете продолжить обход с помощью inVertex().

. Чтобы получить входящие вершины, вы должны выполнить:

for v in g.E().inV().toList():
        print(v)

Чтобы получить свойства ребер и оба свойства вершин в одном запросе,Вы можете использовать project:

g.E().project("values", "in", "out")
    .by(valueMap(true))
    .by(inV().valueMap(true))
    .by(outV().valueMap(true))
0 голосов
/ 24 сентября 2019

Глядя на исходный код на https://github.com/apache/tinkerpop/blob/master/gremlin-python/src/main/jython/gremlin_python/structure/graph.py (см. Ниже), доступны следующие свойства:

для всех элементов:

e.id
e.label

для ребер:

e.inV
e.outV

Плохая новость заключается в том, что сначала нужно получить свойства, поэтому не так просто получить доступ к идентификаторам, меткам и свойствам в одной инструкции python.

class Element(object):
    def __init__(self, id, label):
        self.id = id
        self.label = label

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.id == other.id

    def __hash__(self):
        return hash(self.id)


class Vertex(Element):
    def __init__(self, id, label="vertex"):
        Element.__init__(self, id, label)

    def __repr__(self):
        return "v[" + str(self.id) + "]"


class Edge(Element):
    def __init__(self, id, outV, label, inV):
        Element.__init__(self, id, label)
        self.outV = outV
        self.inV = inV

    def __repr__(self):
        return "e[" + str(self.id) + "][" + str(self.outV.id) + "-" + self.label + "->" + str(self.inV.id) + "]"
...