2

我在 Neo4j 中做一个“朋友的朋友”类型的 MATCH。唯一让我失望的是试图按日期限制所有关系。

基本图是这样的:

在此处输入图像描述

图表的“真实”版本有 10 个一级朋友和 3385 个二级朋友。

尽管我没有在上图中的每个边缘上放置日期属性,但确实如此。任何日期都没有顺序。

总体思路非常简单:我想确保忽略任何具有比预定最大日期更早的日期属性的关系。

稍微棘手的部分是,如果在第一个关系中违反了最大日期约束(就像上图中从节点脱落的三个边之一),那么该边被分成两半并且没有其他遍历该路径应该能够发生。(例如,我不想要任何叶节点)。

我写了这个:

MATCH
(n)-[f1:FRIEND]-()-[f2:FRIEND]-(m)
WITH n, m,split('1962-1-1', '-') AS maxdate
WHERE n.person_id='180'
AND(
(
toInt(maxdate[0]) > toInt(split(f1.date, '-')[0])
)   
OR
(
toInt(maxdate[0]) = toInt(split(f1.date, '-')[0])
 AND
toInt(maxdate[1]) >= toInt(split(f1.date, '-')[1])
))
AND(
(
toInt(maxdate[0]) > toInt(split(f2.date, '-')[0])
)   
OR
(
toInt(maxdate[0]) = toInt(split(f2.date, '-')[0])
 AND
toInt(maxdate[1]) >= toInt(split(f2.date, '-')[1])
))
RETURN m;

这个代码块运行了大约 20 分钟,最终似乎产生了接近我目标的结果。这是它在浏览器中的样子:

在此处输入图像描述

(它有 350 个节点)

首先,我承认这显然是一些写得很糟糕的代码(在美学和性能方面)。其次,我注意到外围的未关联节点。

我认为发生的情况是,一级关系的约会条件失败,但二级关系没有,所以我最终得到了我不想被包括在内的“朋友的朋友”。

如何修改我的日期条件,以便在第一度边无效时消除这些独立节点?

如果有人有任何见解,我将不胜感激。(不要太糊涂,但感谢 SO 社区,我已经相对较快地走了很远,为此我很感激。)

4

1 回答 1

4

首先它不应该运行那么长时间,主要原因是您的节点上没有标签+索引

首先添加这些:

CREATE CONSTRAINT ON (p:Person) ASSERT p.person_id is unique;
MATCH (n) where exists(n.person_id) SET n:Person;

如果您有时间yyyy-mm-dd(至少我希望如此),您可以直接比较它们:(即 2 位数字01)即'2012-01-10' > '2011-08-31'

WITH '1962-01-01' AS maxdate
MATCH (n:Person)-[f1:FRIEND]-()-[f2:FRIEND]-(m:Person)
WHERE n.person_id='180' AND f1.date < maxdate and f2.date < maxdate
RETURN m;

您还可以使用缩写形式:(n:Person {person_id:'180'})

如果您想对路径中的关系有一个通用表达式,rels请在您的可变长度路径模式中使用一个变量(然后是一个集合):

WITH '1962-01-01' AS maxdate
MATCH (n:Person {person_id:'180'})-[rels:FRIEND*2]-(m:Person)
WHERE ALL(r in rels WHERE r.date < maxdate)
RETURN m;

你也可以使用rels(path)

WITH '1962-01-01' AS maxdate
MATCH path = (n:Person {person_id:'180'})-[:FRIEND*2]-(m:Person)
WHERE ALL(r in rels(path) WHERE r.date < maxdate)
RETURN m;

或者如果路径的关系是相互关联的:

WITH '1962-01-01' AS maxdate
MATCH (n:Person  {person_id:'180'})-[rels:FRIEND*2]-(m:Person)
WHERE ALL(idx in range(0, size(rels)-2) WHERE (rels[idx]).date < maxdate AND (rels[idx]).date < (rels[idx+1]).date)
RETURN m;
于 2016-05-21T10:53:25.147 回答