я создал структуру категорий в базе данных графа «neo4j».
У меня есть узлы и отношения, все идеально.
Я использую Neoxygen Neoclient для PHP для доступа к данным. Как я могу эффективно запросить весь граф категорий (включая структуру) из моего корневого элемента?
MATCH (a:`Category`{category_id:0})-[r:HAS_CHILD*]->(b:`Category`)
RETURN b,r
Моя желаемая структура в PHP:
— корень
— Категория А
——— Подкатегория AB
— Категория Б
— категория C
——— Подкатегория CA
—————— Подкатегория CAA
…
Есть идеи?
Заранее спасибо.
mr_g
Это полностью выполнимо и удобно в NeoClient Neoxygen.
Первое, что нужно сделать, это активировать средство форматирования ответа:
$client = ClientBuilder::create()
->setAutoFormatResponse(true)
->addConnection(xxx...)
->build();
Во-вторых, в отношении вашего запроса я бы определенно установил предел глубины, чтобы избежать поведения памяти в зависимости от связности вашего графа:
MATCH (a:`Category`{category_id:0})-[r:HAS_CHILD*..20]->(b:`Category`)
RETURN b,r
Затем вы можете отправить его клиенту и воспользоваться тем, чтобы клиент переназначил результаты в виде графа:
$query = 'MATCH (a:`Category`{category_id:{id}})-[r:HAS_CHILD*..20]->(b:`Category`)'
RETURN b,r';
$children = $client->sendCypherQuery($q, ['id'=>0])->getResult()->getNodes();
Теперь каждый узел будет знать, что у него есть, поскольку отношения и отношения знают свои начальные и конечные узлы, например:
$children
узлы в первой глубине, так
$rels = $children->getOutboundRelationships();
$nodes = [];
foreach ($rels as $rel) {
$nodes[] = $rel->getEndNode();
}
$ узлов теперь содержит все узлы в глубине 2.
В настоящее время нет способа получить напрямую подключенные узлы из объекта узла, не получив сначала отношения, возможно, что-то, что я могу добавить к клиенту.
Cypher возвращает табличные данные, поэтому, если вы хотите получить древовидную иерархию, самый эффективный способ — это вернуть все пути от корня до листьев. Путь является коллекцией / массивом узла- (отношения-узла) * (то есть это нечетное число объектов, всегда содержащих узел на каждом конце с чередующимися узлами и отношениями). Вот шифр того, как вы это сделаете:
MATCH path(a:`Category`{category_id:0})-[r:HAS_CHILD*]->(b:`Category`)
WHERE NOT(b-[:HAS_CHILD]->())
RETURN b,r
WHERE
Предложение гарантирует, что вы возвращаете только все пути к листьям. Вы можете вернуть все категории в дереве, которые также дадут вам частичные пути, но все эти частичные пути содержатся в каком-то более длинном пути, так что в итоге вы получите больше данных, чем вам нужно.
Как только у вас есть пути (я не уверен, в какой форме они отображаются в Neoclient, так как я не парень PHP), вы можете построить иерархическую структуру данных в памяти из результатов. Если я правильно помню, структура типа карта / словарь в PHP — это ассоциативный массив.
Схема:
Indexes
ON :Category(category_id) ONLINE (for uniqueness constraint)
Constraints
ON (category:Category) ASSERT category.category_id IS UNIQUE
Запрос:
MATCH(c:Category) RETURN c