TL:DR:
我需要找到最高效的Cypher查询,该查询将使具有特定关系类型的节点连接到特定节点类型,然后检索这些节点之间的连接,筛选出连接最紧密的150个节点,并显示他们给用户。
我在下面提出了一个使用APOC关系属性查询的方法,但是我认为它可以提高效率,因此我正在寻找您的建议。
长期解释:
在我的数据模型中,我有以下类型的节点:
:Concept
:Context
:User
:Statement
这用于文本网络分析,因此基本思想是:Concepts
出现在:Statements
中,属于由某个:Context
添加的某个:User
。
它们还具有属性,例如uid
(唯一ID)和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
;
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
中答案 0 :(得分:2)
您正在生成这些:Concept节点的笛卡尔积,这会降低查询速度。
您可以尝试以下方法:
MATCH (c:Concept)-[:AT]->(:Context{name:'decon',by:'15229100-b20e-11e3-80d3-6150cb20a1b9'})
WHERE (c)-[:BY]->(:User {uid:'15229100-b20e-11e3-80d3-6150cb20a1b9'})
// AND <additional predicate for desired :Statement>
WITH collect(c) as concepts
UNWIND concepts as c
WITH c, size([(c)-[:TO]->(c2) WHERE c2 in concepts | c2]) as connections
ORDER BY connections DESC
LIMIT 150
RETURN c
当然,您希望在:Context(by)上建立索引,以便快速进行初始匹配。