WITH

Введение

Предложение WITH позволяет обрабатывать выходные данные до того, как они будут переданы в последующие части запроса. Такая обработка может изменить структуру и/или количество записей в результирующем наборе.

Как и RETURN, WITH поддерживает псевдонимы столбцов для включения выражений в поток результатов.

WITH также разделяет операции чтения графа от операций записи. Каждая часть запроса Cypher должна быть либо только для чтения, либо только для записи. Необязательное предложение WITH требуется при переходе от операции записи (например, CREATE, SET, REMOVE) к операции чтения (например, MATCH, WHERE).

В YMatrix AGE типичные сценарии использования WITH включают:

  1. Промежуточная обработка («конвейер»)
    WITH выступает как промежуточный этап конвейера: он преобразует результаты предшествующего предложения перед их передачей далее.
    Пример:
    MATCH (p:Person) WITH p ORDER BY p.age DESC LIMIT 3 RETURN p.name
    Сначала находятся все вершины типа Person; WITH сортирует их по возрасту и ограничивает выборку тремя самыми старшими; наконец, RETURN возвращает только значение свойства name. Без WITH такие промежуточные фильтрация и сортировка невозможны в RETURN.

  2. Псевдонимы столбцов (аналогично RETURN)
    WITH присваивает псевдонимы выражениям для их дальнейшего использования в последующих предложениях.
    Пример:
    MATCH (p:Person) WITH p.name AS name, p.age AS age WHERE age > 30 RETURN name
    Предложение WITH переименовывает свойства, позволяя ссылаться на них в последующих частях запроса по новым именам.

  3. Разделение операций чтения и записи
    Согласно семантике Cypher, каждый фрагмент запроса должен быть либо только для чтения, либо только для записи. CREATE — это операция записи; MATCH и WHERE — операции чтения. Для объединения операций записи и чтения обязательно используется WITH.
    Пример:
    CREATE (a:Person {name: 'Tom'}) WITH a MATCH (a)-[:KNOWS]->(b) RETURN b
    Опускание WITH a вызовет ошибку — прямой переход от CREATE к MATCH нарушает правило изоляции чтения и записи.

  4. Глобальная сортировка
    В YMatrix AGE одно лишь ORDER BY не гарантирует глобально упорядоченных результатов по всем segment'ам. Поэтому комбинация ORDER BY + LIMIT не гарантирует получение первых N строк из всего набора данных.
    Чтобы обеспечить глобальную сортировку, примените ORDER BY после предложения WITH — это инициирует перемещение данных (операцию сбора), в результате которой строки объединяются на одном segment'е перед сортировкой и ограничением.

    • RETURN p ORDER BY p.age LIMIT 3: каждый segment выполняет локальную сортировку и ограничение → итоговый результат не гарантирует попадание в него глобальных трёх самых старших записей.
    • WITH p ORDER BY p.age LIMIT 3 RETURN p: WITH инициирует перемещение данных; глобальная сортировка и ограничение выполняются после объединения.

Фильтрация результатов агрегации

Агрегированные значения можно фильтровать только с помощью предложения WITH.

Запрос

SELECT *
FROM cypher('graph_name', $$
    MATCH (david {name: 'David'})-[]-(otherPerson)-[]->()
    WITH otherPerson, count(*) AS foaf
    WHERE foaf > 1
    RETURN otherPerson.name
$$) AS (name agtype);

Возвращает имена лиц, связанных с 'David', имеющих более одной исходящей связи.

Результат

name
"Anders"
(1 строка)

Сортировка перед collect

Можно отсортировать результаты перед их передачей в collect, чтобы получить упорядоченный список.

Запрос

SELECT *
FROM cypher('graph_name', $$
    MATCH (n) WITH n
    ORDER BY n.name DESC LIMIT 3
    RETURN collect(n.name)
$$) AS (names agtype);

Возвращает список до трёх имён, отсортированных по убыванию лексикографического порядка.

Результат

names
["Emil","David","Ceasar"]
(1 строка)

Ограничение ветвей при поиске путей

Можно находить пути, применять LIMIT для ограничения количества найденных путей, а затем использовать ограниченный набор результатов как входные данные для дальнейшего сопоставления шаблонов — в том числе для дополнительных ограниченных поисков.

Запрос

SELECT *
FROM cypher('graph_name', $$
    MATCH (n {name: 'Anders'})-[]-(m) WITH m
    ORDER BY m.name DESC LIMIT 1
    MATCH (m)-[]-(o)
    RETURN o.name
$$) AS (name agtype);

Находит все узлы, связанные с 'Anders', сортирует их по имени в обратном порядке, выбирает первый, затем находит все узлы, связанные с этим узлом, и возвращает их имена.

Результат

name
"Anders"
"Bossman"
(2 строки)