我有大量代表帐户的节点,我们可以将其标记为(a :Account)
。每个(:Account)
都可能连接数万个(t :Transaction)
节点,每个节点代表涉及该帐户的交易的数据。
(:Transaction)
节点具有date
属性。给定一个查询日期,对于查询日期之前或当天发生的每个(a :Account)
,获取最新(:Transaction)
节点的最有效方法是什么?这可能是一种方法:
// run for all address nodes
match (a :Address)
with distinct a
optional match (a)-->(t :Transaction)
where t.timestamp <= date("2014-03-07")
with a, t
where t.date = max(t.date)
return a, t
但是,当连接到每个(a)
的(t)
数量变得非常大时,我不确定这种方法是否非常有效。有没有办法编写查询或索引数据库,以便查询时间与帐户数量线性缩放,而不管连接到这些帐户节点的事务数量如何?
为了披露,我在neo4j社区论坛上发布了这个问题的一个版本,但我希望这个网站上的更大流量会给这个问题更多的曝光率。
在 neo4j 3.5 中,添加了新的"索引支持的排序依据"优化。这意味着,如果您创建一个"本机"索引(有关详细信息,请参阅此处),则该索引将按排序顺序存储,并且使用该索引的属性上的ORDER BY
子句实际上不必执行任何排序。
因此,假设您已经在索引中创建了:Transaction(timestamp)
,如下所示:
CREATE INDEX ON :Transaction(timestamp);
然后,在 Neo4j 3.5+ 中,此查询(带有使用该索引的可选提示)在查找每个Address
具有最大timestamp
的Transaction
时应避免任何排序:
MATCH (a:Address)-->(t:Transaction)
USING INDEX t:Transaction(timestamp)
WHERE t.timestamp <= date("2014-03-07")
WITH a, t
ORDER BY t.timestamp DESC
RETURN a, COLLECT(t)[0] AS transaction
此查询应执行以下操作:
- 使用该索引获取具有适当
timestamp
的所有Transaction
节点(按降序排列,不进行排序)。 - 获取与每个
Transaction
相关的Address
节点。 - 对于每个不同的
Address
节点,创建一个所有相关Transaction
节点的列表(按降timestamp
顺序排列,不进行排序),并从列表中获取第一个节点。 - 返回每个不同的
Address
节点及其最新的相应Transaction
节点。
此查询将随相应Transactions
的数量线性缩放。如果您的用例允许,您可以通过在WHERE
子句中设置下限来减少适当Transactions
的数量,从而更快地获得结果。