MATCH p=(u: User)-[: MemberOf*1..]->(g: Group) RETURN p
Другой пример – получить все компьютеры, где пользователи являются локальными администраторами:
MATCH p=(u: User)-[: MemberOf|AdminTo*1..]->(c: Computer) RETURN p
Построение графа со всеми непрямыми связями потребует большого количества ресурсов, и, скорей всего, база не выдержит и упадет. Для решения этой проблемы можно использовать операторы ShortestPath и AllShortestPaths. Разница между ними в том, что первый находит один короткий путь, а второй – все, при условии, что они существуют.
Для использования коротких путей необходимо поместить шаблон в круглые скобки. Так, предыдущий пример будет выглядеть следующим образом:
MATCH p=ShortestPath((u: User)-[*1..]->(c: Group)) RETURN p
Совет
Ограничение количества переходов поможет найти самые короткие пути.
В интерфейсе BloodHound в форме Поиск путей (Pathfinding) используется оператор AllShortestPaths, который применяется для поиска коротких путей между двумя указанными узлами.
Оператор OPTIONAL MATCH
Оператор OPTIONAL MATCH работает точно так же, как и MATCH; разница в том, что при использовании OPTIONAL MATCH будет добавлять NULL для недостающих элементов.
Рассмотрим два примера, в которых будем искать локальных администраторов на компьютерах с помощью операторов MATCH и OPTIONAL MATCH.
MATCH (u: User)
MATCH (u)-[r: AdminTo]->(c: Computer)
RETURN u.name, c.name
Рис. 3.10. Результат с MATCH
MATCH (u: User)
OPTIONAL MATCH (u)-[r: AdminTo]-(c: Computer)
RETURN u.name, c.name
Рис. 3.11. Результат с OPTIONAL MATCH
Как можно увидеть на рисунке 3.11, там, где нет прав локального администратора, neo4j выставил null. То же самое в графическом представлении: мы получим всех пользователей, и только у некоторых будет связь AdminTo с компьютерами.
Рис. 3.12. Графическое представление OPTIONAL MATCH
Условия фильтрации запросов
Ранее мы уже использовали фильтры по меткам User и Computer, но только в некоторых случаях этого будет достаточно. Для указания более точных критериев поиска применяется оператор WHERE, который может относиться ко всем свойствам узла и связи.
Обычно оператор WHERE используется после формирования шаблона, но он может быть применен и внутри узла, и все условия будут относиться только к этому узлу:
MATCH (g: Group) WHERE g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN g.name
MATCH (g: Group WHERE g.name = "DOMAIN ADMINS@DOMAIN.LOCAL") RETURN g.name
Эти два запроса будут иметь одинаковый вывод, но второй запрос будет читаться сложнее.
Внимание
Помним, что Cypher чувствителен к регистру для свойств узла.
Рассмотрим синтаксис использования оператора WHERE на простых примерах.
Для указания точного вхождения используется оператор сравнения =.
Например, найти всех членов группы администраторов домена:
MATCH (u: User)-[r: MemberOf*0..]->(g: Group) g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name
Кроме строковых значений могут приниматься булевы значения FALSE и TRUE или числовые. Например, найти все незаблокированные учетные записи компьютеров:
MATCH (c: Computer) WHERE c.enabled = TRUE return c
Другой способ использовать точное вхождение – это указать фильтр запроса в узлах. Фильтр задается в фигурных скобках по шаблону <свойство>:<значение>. Например, определить, на каких машинах используется LAPS, можно следующим образом:
MATCH (c: Computer {haslaps: true}) return c
Можно добавить несколько условий. В таком случае они разделяются запятой. Например, выбрать только незаблокированные объекты и компьютеры, на которых используется LAPS.
MATCH (c: Computer {enabled: true, haslaps: true}) return c
Если мы хотим указать метку в операторе WHERE, то вместо знака равенства используется двоеточие.
MATCH (c) WHERE c: User RETURN c
Имя связи тоже можно указывать в WHERE. В данном случае используется type(), так как у связи нет свойства имени.
MATCH p=(c: Computer)-[r]->(u: User) WHERE type(r) = "HasSession" RETURN p
Как и узлы, связь может иметь свойства, и фильтрация по ним будет иметь точно такой же принцип. Например, найти все связи между пользователями и компьютерами, где связь имеет свойство isacl в значении TRUE:
MATCH p=(u: User)-[r]-(c: Computer) WHERE r.isacl = TRUE RETURN p
Оператор не равно <> противоположен предыдущему оператору. Например, найти все группы, которые не являются контроллерами домена: