Создать новый объект обхода из списка вершин

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

g.V().filter(bothE().limit(50).count().is(lt(50)))

Это дает мне список вершин, которые я хочу сохранить.

Как я могу создать объект traversal, который включает только эти вершины?

Фон

Мне нужно вычислить k-шаговую окрестность каждой отдельной вершины в графе, которая отфильтровывает вершины с большим количеством ребер (например, ‹50). Отфильтрованный граф имеет несколько миллионов ребер и вершин.

Первый способ сделать это, который пришел в голову, заключался в том, чтобы сначала отфильтровать граф, сохранить результат в виде нового подграфа, а затем перебрать каждую вершину, чтобы найти окрестности k-го шага. Для одной вершины v код соседства с k = 5 скачками:

g.V(v).repeat(__.bothE().bothV()).times(5).dedup().toList()

Лучшим способом может быть итерация каждой вершины в исходном нефильтрованном графе и игнорирование ребер, прикрепленных к вершине с большим количеством ребер, но я не уверен, как это сделать.

Попытка 1:

filtered_edges = g.V().filter(bothE().limit(50).count().is_(lt(50))).outE().toList()
subgraph = g.E(filtered_edges).subgraph('subGraph').cap('subGraph').next()

К сожалению, при использовании gremlinpython выдается ошибка (StreamClosedError: Stream is closed). Выполнение других - возможно, менее затратных - запросов до и после появления этой ошибки не приводит к аналогичным ошибкам, поэтому соединение с оболочкой gremlin все еще существует. Код также работает в оболочке gremlin (заменяя is_ на is).

Я предполагаю, что это связано с тем, что я отправляю так много данных между сервером gremlin и Python, но не уверен, почему это может быть проблемой.

Попытка 2:

Использование клиента gremlin. Я пробовал перезаписать другой объект обхода с именем l. Однако операция перезаписи не выполняется (l = subgraph.traversal();).

gremlin_client = client.Client('ws://{}:{}/gremlin'.format('localhost', 8192), 'g', message_serializer=serializer.GraphSONSerializersV3d0())


command = "filtered_edges = g.V().filter(bothE().limit(50).count().is(lt(50))).outE().toList(); subgraph = g.E(filtered_edges).subgraph('subGraph').cap('subGraph').next(); l = subgraph.traversal();"
gremlin_client.submit(command).all().result()

person Ian    schedule 09.08.2019    source источник


Ответы (1)


Вы можете продолжить обход оттуда:

s.V().filter(bothE().limit(50).count().is(lt(50))).out().has(...)....

or:

List<Vertex> list = s.V().filter(bothE().limit(50).count().is(lt(50))).toList()
s.V(list).out().has(...)....
person stephen mallette    schedule 09.08.2019
comment
Спасибо, Стивен, единственная проблема заключается в том, что я хочу использовать отфильтрованный график несколько раз, поэтому не хочу повторно вычислять s.V(list) каждый раз, когда я запускаю запрос. Как я могу сохранить s.V(list), чтобы использовать его повторно? - person Ian; 09.08.2019
comment
Я не совсем уверен, какие у вас есть дополнительные возможности. Список вершин отключен от графа, поэтому повторный обход их для сбора всего, что с ними связано, на отдельном обходе означает повторный поиск их. Если вы используете Java, я думаю, вы могли бы использовать subgraph(), который вернул бы TinkerGraph только с тем, что вам нужно, а затем вы могли бы запросить этот подграф. - person stephen mallette; 09.08.2019
comment
Привет, Стивен. Я попытался решить эту проблему несколькими способами (см. Обновления), но мне не повезло. Буду очень признателен, если вы подскажете, в чем я ошибаюсь - person Ian; 09.08.2019
comment
обратите внимание, что я сказал, что если вы используете Java, то subgraph() - это вариант. gremlinpython еще не поддерживает этот конкретный шаг (в python нет TinkerGraph для подграфа). использование сценария в вашей попытке 2 должно работать, но только в том случае, если вы используете сеанс и сохраняете TinkerGraph на сервере (т.е. устанавливаете переменную и ничего не возвращаете, а затем обращаетесь к ней при следующем запросе). По отдельности, зачем запрашивать все ребра с g.E() и нужны ли вам все ребра в вашем подграфе (нужными вам вершинами были только те, у которых меньше 50 ребер, но какие именно ребра вам нужны)? - person stephen mallette; 09.08.2019
comment
Тем не менее, сеансы - не лучшее решение. Я все еще не уверен, что понимаю, какую проблему вы пытаетесь решить здесь, поскольку весь объем того, что вы пытаетесь сделать, на самом деле не объясняется. сколько дополнительных запросов вы пытаетесь выполнить для горстки вершин, которые вы изначально находите? это мутации или просто дополнительные чтения для получения данных? если это просто дополнительные чтения, каков характер этих чтений (например, глубокий обход всего графа? дальнейшая фильтрация только этих вершин по свойству?). я не знаю ... может быть вам нужно сформировать новый вопрос с более подробной информацией. - person stephen mallette; 09.08.2019
comment
Привет, Стивен, спасибо за понимание. Я добавил некоторую предысторию вопроса, который, надеюсь, немного лучше контекстуализирует мой запрос, есть ли способ адаптировать запрос (см. Выше: код для поиска узлов в окрестности k-hop) на лету, используя where условие вместо того, чтобы сначала выполнить полный фильтр? Извините, этот вопрос стал таким касательным! - person Ian; 09.08.2019
comment
На самом деле, я думаю, что решил. Для данной вершины v сначала запросите, имеет ли она менее 50 ребер, и если да: g.V(v).repeat(__.bothE().bothV().where(__.bothE().count().is(lt(50)))).times(5).dedup().toList(). Извиняюсь за мою окольную методологию ~ - person Ian; 09.08.2019