TL: DR:
Мне нужно найти наиболее эффективный запрос Cypher, который бы связывал узлы с определенным типом узлов с определенным типом отношений, а затем извлекатьсоединений между этими узлами, отфильтруйте 150 лучших из них и покажите их пользователю.
Я предлагаю один ниже, используя запрос свойства отношений APOC, но я думаю, что его можно сделать более эффективным, поэтому я жду вашего совета.
ДЛИННОЕ ОБЪЯСНЕНИЕ:
В моей модели данных у меня есть узлы типа:
:Concept
:Context
:User
:Statement
Это используется для анализа текстовой сети, поэтомуосновная идея заключается в том, что :Concepts
появляются в :Statements
, которые принадлежат определенному :Context
, добавленному определенным :User
.
Они также имеют свойства, такие как uid
(уникальный идентификатор) и name
(название).
Каждый :Concept
связан с любым другим :Concept
с типом направленного отношения :TO
.
Если :Concept
принадлежит :Context
, оно имеет отношение :AT
к этому :Context
Если :Concept
сделано с помощью :User
, то оно подключеноэтому пользователю с отношением типа :BY
.
Я также добавил свойства в отношения, чтобы они указывали, какой пользователь установил соединение :TO
и в каком контексте он появился.
Мне нужно получить список узлов и их взаимосвязей в определенном контексте, поэтому в настоящее время я использую запрос Cypher / APOC типа:
CALL apoc.index.relationships('TO','user:15229100-b20e-11e3-80d3-6150cb20a1b9')
YIELD rel, start, end
WITH DISTINCT rel, start, end
MATCH (ctx:Context)
WHERE rel.context = ctx.uid
AND (ctx.name="decon" )
RETURN DISTINCT start.uid AS source_id,
start.name AS source_name,
end.uid AS target_id,
end.name AS target_name,
rel.uid AS edge_id,
ctx.name AS context_name,
rel.statement AS statement_id,
rel.weight AS weight
Он работает довольно хорошо, однако проблема заключается в том, что еслиГрафик большой (например, более 1000 узлов и 5000 соединений), его запрос занимает слишком много времени.
Итак, я хочу иметь возможность фильтровать количество получаемых отношений.
Используя приведенный выше запрос, это довольно сложно сделать, так как я хочу отфильтровать 150 самых верхних подключенных узлов, и мне нужно сначала получить данные, чтобы сделать это.
ИтакЯ подумал, что, возможно, мне следует изменить логику своего запроса и вместо этого:
1) Запросить интересующий меня :Context
1062 *
2) Подключить все узлы :Concept
к этому;
3) Найти все отношения извлеченных :Concept
узлов друг к другу;
4) Получить X (150) самых верхних :Concept
соединенных узлов, не обращая внимания на остальные.
5) Покажите их пользователю.
Я попробовал следующий запрос:
MATCH (ctx:Context{name:'decon',by:'15229100-b20e-11e3-80d3-6150cb20a1b9'})
WITH ctx MATCH (c1:Concept)-[:AT]->(ctx),
(c2:Concept)-[:AT]->(ctx)
WITH c1, c2
MATCH (c1)-[rel:TO]->(c2)
RETURN DISTINCT rel;
Но, похоже, это займет гораздо больше времени.
Мне также нужно отфильтровать отношения между этими узлами, чтобы они отображали только отношения, сделанные определенным :User
и появляющиеся только в определенных :Statement
.
У любого есть идея, что еще я мог бы попробовать?
PS Исходный код находится в https://github.com/noduslabs/infranodus/blob/master/lib/entry.js#L573