Написание запросов шаблонов графа в Microsoft Fabric

Сопоставление шаблонов графа позволяет описать структуру данных, которые вы хотите найти с помощью интуитивно понятного визуального синтаксиса. Вместо объединения таблиц вы записываете шаблоны, которые выглядят как сами связи — узлы, подключенные к краям. В этой статье показано, как создавать запросы шаблонов GQL для распространенных сценариев в графе в Microsoft Fabric.

В примерах используется пример набора данных социальной сети. Полный справочник по синтаксису шаблонов см. в шаблонах графов GQL.

Необходимые условия

Сопоставьте прямые связи

Базовый шаблон соответствует типу узла, определенному граничному типу и другому типу узла. Синтаксис выглядит как схема связи.

Например, чтобы найти до 100 человек, которые работают в определенной компании:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name
LIMIT 100

Используйте ненаправленный граничный шаблон, если вы не знаете или не заботитесь о направлении. Например, чтобы найти до 100 взаимных знакомых независимо от того, кто инициировал подключение:

MATCH (a:Person)-[:knows]-(b:Person)
RETURN a.firstName, b.firstName
LIMIT 100

Note

Граф в настоящее время не поддерживает создание ненаправленных ребер, но вы можете делать запросы на ребра в любом направлении с помощью синтаксиса -[:label]-.

Фильтрация шаблонов с использованием inline WHERE

Поместите WHERE внутри шаблона для фильтрации узлов и рёбер по мере их сопоставления. Этот подход эффективнее, чем фильтрация задним числом.

Например, чтобы найти людей, родившихся до 1990 года, которые работают в компании, название которой начинается с "A":

MATCH (p:Person WHERE p.birthday < 19900101)-[:workAt]->(c:Company WHERE c.name STARTS WITH 'A')
RETURN p.firstName, p.lastName, c.name

Отфильтруйте свойства ребра, чтобы ограничить соответствие связей. Например, чтобы вернуть только тех, кто начал работать в компании в 2010 году или позже:

MATCH (p:Person)-[w:workAt WHERE w.workFrom >= 2010]->(c:Company)
RETURN p.firstName, c.name, w.workFrom

Сопоставление многоэтапных связей

Используйте шаблоны переменной длины для обхода нескольких прыжков в одном выражении. Укажите минимальное и максимальное количество прыжков с синтаксисом {min,max} .

Например, чтобы найти до 100 человек, находящихся в пределах от двух до четырёх уровней дружбы с Алисой:

MATCH (src:Person WHERE src.firstName = 'Alice')-[:knows]->{2,4}(dst:Person)
RETURN dst.firstName, dst.lastName
LIMIT 100

Чтобы найти до 100 непосредственных и вторичных связей (один или два хопа) из точки Алисы:

MATCH (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,2}(dst:Person)
RETURN DISTINCT dst.firstName, dst.lastName
LIMIT 100

Управление перемещением с режимами пути

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

Режим траектории Behavior Следует использовать в следующих случаях...
WALK Разрешает повторяющиеся узлы и края Требуется необработанный обход без ограничений. Редко требуется; в основном полезно для поисковых запросов.
TRAIL Не повторяющиеся края (по умолчанию) Вы хотите избежать повторного прохождения той же связи, но один и тот же узел может появляться через различные связи. Хорошо подходит для большинства обходных запросов.
SIMPLE Нет повторяющихся узлов, кроме начального и конечного Вы хотите, чтобы узел не появлялся более одного раза в середине пути, но разрешаете пути, которые возвращаются к началу. Полезно для обнаружения циклов.
ACYCLIC Никаких повторяющихся узлов Необходимо обеспечить, чтобы ни один узел не встречался в пути более одного раза. Используется для строгих иерархий, происхождения или любого обхода, при котором повторное посещение узла приведет к неправильным результатам.

WALK является самым разрешительным режимом и ACYCLIC является самым строгим. TRAIL — это значение по умолчанию и работает хорошо для большинства запросов. Используйте более строгий режим, только если для вашего варианта использования требуется.

Чтобы проиллюстрировать разницу, рассмотрим путь Алиса → Боб → Кэрол → Боб:

  • WALK — разрешает этот путь. Узлы и края могут повторяться свободно.
  • TRAIL — разрешает этот путь. Боб появляется дважды, но каждое ребро используется по-разному (Алиса→Боб и Кэрол→Боб являются отдельными рёбрами), поэтому рёбра не повторяются.
  • SIMPLE — блокирует этот путь. Боб появляется более одного раза, и SIMPLE позволяет узлу повторяться, только если он является и началом, и концом пути (замкнутый цикл). Здесь Алиса является началом, и Боб является конец, поэтому никаких исключений не применяется.
  • ACYCLIC — блокирует этот путь. Боб появляется более одного раза в любом месте по пути.

В следующем примере показано, как с помощью TRAIL подсчитывать количество различных путей, ведущих к первым 100 человекам, достижимым в сети Алисы в пределах четырех хопов.

MATCH TRAIL (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,4}(dst:Person)
RETURN dst.firstName, dst.lastName, count(*) AS pathCount
LIMIT 100

Используйте ACYCLIC для возвращения до 100 человек, достижимых от Алисы за четыре перехода, где каждый человек на пути уникален.

MATCH ACYCLIC (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,4}(dst:Person)
RETURN dst.firstName, dst.lastName
LIMIT 100

Tip

Для больших графов всегда устанавливайте верхнюю границу для шаблонов переменной длины ({1,4} а не {1,}). Неограниченный обход по плотным графам может достигать пределов тайм-аута запроса. См. текущие ограничения.

Использование переменной для выражения общих сущностей

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

Например, чтобы найти до 100 пар людей, которые знают друг друга и работают в одной компании:

MATCH (c:Company)<-[:workAt]-(a:Person)-[:knows]-(b:Person)-[:workAt]->(c)
RETURN a.firstName, b.firstName, c.name
LIMIT 100

Переменная c повторно используется для обоих workAt целевых объектов, поэтому запрос возвращает только пары, где оба человека знают друг друга и работают в одной компании.

Чтобы найти до 100 пар людей, которые оба поставили лайк на один и тот же пост:

MATCH (a:Person)-[:likes]->(post:Post)<-[:likes]-(b:Person)
WHERE a.id < b.id
RETURN a.firstName, b.firstName, post.id
LIMIT 100

Tip

Условие WHERE a.id < b.id предотвращает появление повторяющихся пар (Алиса + Боб и Боб + Алиса) в результатах.

Объединение нескольких шаблонов

Перечислите несколько шаблонов в одном MATCH, разделяя их запятыми. Все шаблоны должны разделять по крайней мере одну переменную, чтобы они были правильно соединены.

Например, чтобы найти до 100 человек вместе с их местом работы и городом проживания:

MATCH (p:Person)-[:workAt]->(c:Company),
      (p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, c.name AS company, city.name AS city
LIMIT 100

Общая переменная p соединяет два шаблона. Каждая строка результата представляет одного человека со своей компанией и городом.

Сопоставление необязательных связей

Используйте OPTIONAL MATCH если связь может не существовать для каждого узла. Строки без совпадения сохраняются со значениями NULL , похожими на SQL LEFT JOIN.

Например, вернуть до 100 человек с названием их компании, включая людей без работодателя (то есть, возвращающих NULL для столбца компании):

MATCH (p:Person)
OPTIONAL MATCH (p)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name AS company
LIMIT 100

Используйте IS NULL после OPTIONAL MATCH, чтобы найти до 100 человек, которые не работают в какой-либо компании.

MATCH (p:Person)
OPTIONAL MATCH (p)-[:workAt]->(c:Company)
FILTER c IS NULL
RETURN p.firstName, p.lastName
LIMIT 100