MATCH(u: User) WHERE u.description =~ "(?i).*(парол|passw).*" RETURN u.name, u.description
Оператор RETURN
Для возврата результатов используется оператор
RETURN
. В некоторых случаях RETURN
может заменяться на WITH
, если результаты запроса используются в другом запросе.Внимание
В одном запросе может быть только один
RETURN
, за исключением использования операторов CALL
или UNION
и UNION ALL
.Cypher поддерживает несколько типов возврата результатов. Рассмотрим их.
Примеры вывода результатовВ виде узла
MATCH (d: Domain) RETURN d
В виде графа
MATCH p=(g: Group)-[: GenericAll]-(c: Computer) RETURN p
или
MATCH (g: Group)-[r: GenericAll]-(c: Computer) RETURN g, r, c
Получить все узлы и связи:
MATCH (g: Group)-[r: GenericAll]-(c: Computer) RETURN *
В виде таблицы свойств объектов
MATCH (u: User) RETURN u.name, u.description
По умолчанию название таблицы выводится в виде переменной и названия свойства через точку. Это отображение можно изменить с помощью оператора
AS
:MATCH (u: User) RETURN u.name as Name, u.description AS Description
В виде списка
MATCH(u: User) RETURN collect(u.name)
Получить список компьютеров, на которых пользователь имеет права локального администратора:
MATCH (u: User)-[r: MemberOf|AdminTo*1..]->(c: Computer) RETURN u.name, collect(c.name)
Работа со списками будем рассматриваться дальше.
Уникальные записи, оператор DISTINCTВ предыдущем примере список компьютеров будет содержать повторы, это связано с тем, что разные группы могут входить в группу локальных администраторов и пользователь тоже может входить в эти группы. Чтобы убрать повторы, можно воспользоваться оператором
DISTINCT
.MATCH (u: User)-[r: MemberOf|AdminTo*1..]->(c: Computer) RETURN u.name, collect(DISTINCT c.name)
Оператор COUNTДля подсчета элементов используется оператор
COUNT
. Например, для подсчета количества пользователей в базе данных будет использоваться следующий Cypher-запрос:MATCH (u: User) RETURN count(u)
Другой пример – нужно посчитать, какие узлы имеют права
Owns
и на скольких узлах:MATCH (u)-[r: Owns]->(c) RETURN u.name, count(c)
Считать можно не только узлы, но и связи. В следующем примере мы получим количество связей.
MATCH p=(g: Group)-[r: GenericAll]->(c: Computer) return count(r)
Еще один интересный запрос:
MATCH p=AllShortestPaths((g: User)-[*1..3]->(c: Computer)) return count(p)
Здесь мы ищем все возможные связи от группы пользователей до группы компьютеров с переходами от 1 до 3 и считаем общее количество элементов.
Оператор ORDER BYОператор
ORDER BY
позволяет упорядочивать вывод данных, а оператор DESC
позволяет изменять направление от большего к меньшему. Например, вывести имена всех пользователей домена в алфавитном порядке:MATCH (u: User) RETURN u.name ORDER BY u.name
Или узнать, у какого пользователя больше связей AdminTo:
MATCH (u: User)-[r: MemberOf|AdminTo*1..]->(c: Computer) RETURN u.name, count(c) AS Comps ORDER BY Comps DESC
Оператор LIMITОператор
LIMIT
используется для ограничения количества выводимых элементов. Например, нужно получить первые пять узлов, в которых есть слово ADMIN:MATCH (n) WHERE n.name CONTAINS "ADMIN" RETURN n LIMIT 5
Как говорилось в разделе описания интерфейса BloodHound, поиск по части названия ограничен 10 узлами, и там как раз используется оператор
LIMIT
.Оператор SKIPКак говорилось ранее, по умолчанию браузер neo4j выводит первую тысячу записей, для просмотра следующих можно изменить параметр
Result
view max rows
в настройках или использовать оператор SKIP
. Например, получить список пользователей, у которых атрибут description
не пустой, и пропустить первую тысячу записей:MATCH (u: User) WHERE u.description IS NOT NULL RETURN u.name, u.description SKIP 1000
Случайная выборкаВозможно, для каких-то исследований или демонстраций потребуется случайным образом выбрать пять узлов. В этом случае запрос Cypher получается следующим:
MATCH (g: Group) RETURN g, rand() as rand ORDER BY rand LIMIT 5
Операторы UNION и UNION ALLОператоры
UNION
и UNION ALL
используются для объединения результатов двух разных запросов (рис. 3.13–3.14). Важное условие использования UNION
заключается в том, чтобы названия результатов при выводе совпадали.Например, выведем пользователей и компьютеры двумя разными запросами:
MATCH (m: User) RETURN m
UNION
MATCH (m: Computer) RETURN m
Разница между
UNION
и UNION ALL
в том, что в первом случае повторы опускаются, а во втором они показываются.Разницу можно увидеть только при табличном выводе данных. Рассмотрим пример, в котором будут объединены результаты двух запросов: первый запрашивает всех пользователей, входящих в группу доменных администраторов, второй – в группу доменных пользователей.
MATCH (u: User)-[r: MemberOf]->(g: Group) WHERE g.objectid ENDS WITH '-512' RETURN u.name
UNION
MATCH (u: User)-[r: MemberOf]->(g: Group) WHERE g.objectid ENDS WITH '-513' RETURN u.name
Рис. 3.13. Результат использования UNION
MATCH (u: User)-[r: MemberOf]->(g: Group) WHERE g.objectid ENDS WITH '-512' RETURN u.name
UNION ALL
MATCH (u: User)-[r: MemberOf]->(g: Group) WHERE g.objectid ENDS WITH '-513' RETURN u.name
Рис. 3.14. Результат использования UNION ALL
Во втором случае пользователи
ADMIN
и ADMINISTRATOR
в списке появляются дважды.Объединение путейМожет возникнуть ситуация, в которой нам нужно получить граф, основываясь на результатах другого запроса. В качестве примера выполним два запроса. В первом получим членов группы доменных администраторов, а во втором – на каких компьютерах группа имеет права локального администратора, и результат выведем в одном вызове
RETURN
:MATCH p1=(u: User)-[r: MemberOf*1..]->(g: Group {name: "DOMAIN ADMINS@DOMAIN.LOCAL"})
MATCH p2=(g)-[r1:AdminTo]->(c: Computer)
RETURN p1, p2
Оператор WITH
Как говорилось ранее, в некоторых запросах оператор
RETURN
может быть заменен на WITH
. Оператор WITH
позволяет передавать результаты из одного запроса в другой, где они используются для определения отправных узлов.Внимание
Оператор WITH влияет на область видимости переменных. Если не указать их, то Cypher выдаст ошибку, что переменные не определены. Можно использовать * для указания всех переменных в предыдущем запросе.
Оператор
WITH
можно использовать для манипуляций данными перед выводом информации.В некоторых ситуациях нам нужно получить граф, основываясь на результатах другого запроса. В качестве примера рассмотрим ситуацию, в которой нам нужно получить компьютеры, к которым не применяется доменная политика
DEFAULT DOMAIN CONTROLLERS POLICY.
MATCH (o: GPO)-[r: GPLink*0..]->(n) WHERE o.gpcpath CONTAINS "6AC1786C-016F-11D2–945F-00C04FB984F9"
MATCH (n)-[r1:Contains*1..]->(c: Computer) WITH collect (c.name) AS c1
MATCH (c2:Computer) WHERE NOT c2.name IN c1
RETURN c2.name
В этом запросе на первом шаге мы получаем все
OU
, к которым применяется групповая политика, на следующем шаге определяем все компьютеры, которые принадлежат