Новое в Gremlin_python и GraphDB в целом, мы используем AWS neptune. Я пытаюсь получить список сценариев, которые имеют отношение к набору разных тегов, например. дайте мне все сценарии с тегом A и тегом B. Но набор тегов может быть динамическим (от 1 до 10 элементов).
Вопрос, как я понимаю, в термах GraphDB:
Дайте мне все вершины, от которых исходит ребро с меткой label=tag к вершинам с меткой A и B. Изображение графа
Для нединамического подхода я заставляю его работать с этим героем:
e = g.V().and_(__.out('tag').hasLabel('A'), __.out('tag').hasLabel('B')).label().toList()
Но я не могу заставить это работать со списком тегов. Я также пробовал это, но он просто генерирует оператор OR, и я не нашел способа заставить его это сделать, и:
label_list = ['A','B']
e = g.V().where(__.out('has tag').hasLabel((*label_list))).label().toList()
Я также попробовал этот подход, просто получив сообщение «Соединение было закрыто сервером», я много раз видел это с AWS Neptune, что вместо создания сообщения об ошибке закрывается соединение, а кто-нибудь знает, как это происходит ?:
label_list = ['A','B']
e = g.V().and_(map(lambda x:__.out('has tag').hasLabel(x), label_list)).label().toList()
print(len(e))
Мы тестируем это в блокноте Sage Maker, используя Python 3.8.
Итак, Интернет, не могли бы вы дать мне ответ здесь?
БР Джон
Список включенных в блокнот:
import yaml
from pathlib import Path
import json
import os
#from __future__ import print_function # Python 2/3 compatibility
from gremlin_python import statics
from gremlin_python.structure.graph import Graph
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.strategies import *
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
from gremlin_python.process.traversal import T
from gremlin_python.process.traversal import Order
from gremlin_python.process.traversal import Cardinality
from gremlin_python.process.traversal import Column
from gremlin_python.process.traversal import Direction
from gremlin_python.process.traversal import Operator
from gremlin_python.process.traversal import P
from gremlin_python.process.traversal import TextP
from gremlin_python.process.traversal import Pop
from gremlin_python.process.traversal import Scope
from gremlin_python.process.traversal import Barrier
from gremlin_python.process.traversal import Bindings
from gremlin_python.process.traversal import WithOptions
from argparse import ArgumentParser
from loguru import logger
import nest_asyncio
nest_asyncio.apply()
Вы должны иметь возможность использовать предикат within
для этого, если тест сводится к «имеет любое из этих значений свойств (тегов)».
g.V().out('tag').hasLabel(within('A','B','C'))
ОБНОВЛЕНО: на основе комментариев.
Если вам нужно убедиться, что из начальной вершины есть хотя бы одно ребро для каждого из желаемых типов меток, вы можете изменить приведенный выше запрос следующим образом:
g.V().where(out('tag').hasLabel(within('A','B','C')).
label().dedup().count().is(3))
ОБНОВЛЕНО 22 февраля 2023 г.
В этом конкретном случае within
на самом деле не нужен, хотя оптимизатор запросов должен генерировать один и тот же план запроса независимо. Запрос можно записать так:
g.V().where(out('tag').hasLabel('A','B','C').
label().dedup().count().is(3))
Итак, просто чтобы уточнить, у узлов есть несколько меток, таких как A::B::C
, или должно быть ребро для всех типов меток с заданного начала?
Я обновил ответ примером, который обрабатывает последний случай.
Я добавил изображение с установкой, которая у меня есть. в базе данных более двух узлов сценария 1 и сценария 2. Я не понимаю команды is и inside для работы с gremlin-python и aws-neptune. Это только команды Groovy-консоли? Если я удалю внутри и есть. эта команда по-прежнему генерирует комбинацию ИЛИ.
Это стандартные слова Gremlin, НО — иногда имена шагов Gremlin конфликтуют с зарезервированными словами Python. В таких случаях вам нужно будет добавить к ним символ подчеркивания. Таким образом, is()
при использовании Python становится is_()
. Для within
попробуйте P.within()
- если ни один из них не работает, вам может потребоваться импортировать дополнительные элементы.
Я нашел одно решение проблемы. Больше похоже на питона, чем на Гремлина. Сгладить список кода получилось, но, возможно, есть более читаемое решение.
label_list = ['A','B']
e = g.V().and_(*[__.out('tag').hasLabel(x) for x in label_list]).label().toList()
Обновленный запрос в другом ответе по существу делает это. Удалось ли вам попробовать использовать обсуждаемые исправления для is
и within
?
если я запускаю: e = g.V().where(_.out('tag').hasLabel(P.within('A','B')).label().dedup().count( ).is_(3)) e Блокнот Neptune генерирует: [['V'], ['where', [['out', 'tag'], ['hasLabel', inside(['A', ' B'])], ['label'], ['dedup'], ['count'], ['is', 3]]], ['values', '_ipython_canary_method_should_not_exist'], ['values', ' ipython_canary_method_should_not_exist']] Мне нужно прочитать, что делают используемые вами функции, чтобы понять, что пытается сделать запрос. Но то, что я хотел бы, и то, что выдает мой запрос, - это список вершин, у которых есть краевой тег для вершины A и B.
И снова, если я просто использую операторы wereinin('A','B'))), как вы предлагаете, e = g.V().where(__.out('tag').hasLabel(P.within('A','B'))). label().dedup().toList() len(e) Он по-прежнему генерирует оператор ИЛИ, а не оператор И. НАПРИМЕР. список включает все вершины с ребром (с тегом метки) к вершине с меткой A ИЛИ ребро (с тегом метки) к вершине с меткой B.
Каждый вызов с использованием Python должен заканчиваться «конечным» шагом, таким как next()
, iterate()
, toList()
и т. д. Этот конкретный вызов, вероятно, должен заканчиваться на toList()
, поскольку может быть несколько результатов, и вы, вероятно, захотите их все сразу. Это часть count()
, которая гарантирует, что у вас есть хотя бы один из них.
Да! Это сработало и сейчас. Я был на 100% уверен, что попробовал это с toList в конце. Мне просто нужно прочитать о том, как работает счет и другие шаги снижения барьера.
Есть ли мотивация для отказа от этого решения? Сегодня я провел несколько тестов функции профиля и провел около 20 тестов. время выполнения этого решения составляет от 220 до 600 мс, а решение where/inin/count/is занимает от 3300 до 6500 мс. Я попытаюсь узнать больше о выводе профиля, но я смотрю только на ключ «dur», но также вижу, что «traverserCount» и «elementCount» сильно различаются.
Интересно, что три hasLabel
внутри and
шага показали себя намного лучше, чем метод подсчета. Я буду исследовать это дальше. Я предполагаю, что это как-то связано с тем, что тест and
может завершиться, как только он найдет один из каждого, а не считать их все.
Извините, может быть, я был неясен, я обновил пост. это должно быть "все", а не "есть". Как в логическом И между операторами, а не в ИЛИ. BR Джон