Neo4j:将 Cypher 查询更新为 return 每百分之一的元素

Neo4j: update Cypher query to return every hundredth element

应用背景: 我正在开发由客户端和服务器端组成的应用程序。服务器端每 5 分钟从某个外部 API 馈线消耗数据,将其转换并保存到 Neo4j 图形数据库中。 客户端通过调用服务器端获取所有存储的数据,并根据接收到的数据构建图表:

http://decisionwanted.com/decisions/2/bitcoin

更多保存细节:每次,对于新消耗的数据我创建新的历史值节点 与现有 Value(根)节点的新关系:

问题: 服务器端 returns 通过应用以下 Cypher 查询存储了到目前为止的所有数据:

MATCH (v:Value)-[rvhv:CONTAINS]->(hv:HistoryValue)
WHERE v.id = {valueId}
OPTIONAL MATCH (hv)-[ru:CREATED_BY]->(u:User)
WHERE {fetchCreateUsers}
RETURN ru, u, rvhv, v, hv
ORDER BY hv.createDate DESC

由于每次消费操作后总数据量增加,查询性能开始下降,延迟开始增加。

问题:

  1. 在某些时候,我的图表将包含超过 ~100k 值的历史节点,这会显着降低查询性能。因此,谁能建议更好的方法来存储或检索此类数据?
  2. 我不想一次发送所有存储的数据,而是希望能够根据从客户端收到的时间范围和确定要跳过到下一个元素的数量的步骤来限制 returned 数据的大小应该 returned 的值。

例如:存储了1000个历史值节点。我只想 return 每百分之一的元素,从第一个开始到最后 1000 个。

所以查询的结果集应该包含节点1, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000。

这种方法看起来很适合我。唯一的问题是我如何告诉 Cypher 查询:

MATCH (v:Value)-[rvhv:CONTAINS]->(hv:HistoryValue)
WHERE v.id = {valueId}
OPTIONAL MATCH (hv)-[ru:CREATED_BY]->(u:User)
WHERE {fetchCreateUsers}
RETURN ru, u, rvhv, v, hv
ORDER BY hv.createDate DESC

到return只有百分之一的元素?有人知道怎么做吗?

  1. 因为你的查询在最后使用 ORDER BY,Cypher 必须生成所有结果行,然后对它们进行排序。如果,如问题 #2 所述,您希望将结果限制在一个时间范围内,则应尽早对其进行过滤,以最大程度地减少工作量。例如,如果您只对参数化 startDateendDate 值中的 createDate 值感兴趣:

    MATCH (v:Value)-[rvhv:CONTAINS]->(hv:HistoryValue)
    WHERE v.id = {valueId} AND {startDate} <= hv.createDate <= {endDate}
    OPTIONAL MATCH (hv)-[ru:CREATED_BY]->(u:User)
    WHERE {fetchCreateUsers}
    RETURN ru, u, rvhv, v, hv
    ORDER BY hv.createDate DESC
    
  2. 除了执行上述早期过滤外,以下查询 returns 索引 0、100、200、...、1000 处的行的集合:

    MATCH (v:Value)-[rvhv:CONTAINS]->(hv:HistoryValue)
    WHERE v.id = {valueId} AND {startDate} <= hv.createDate <= {endDate}
    OPTIONAL MATCH (hv)-[ru:CREATED_BY]->(u:User)
    WHERE {fetchCreateUsers}
    WITH ru, u, rvhv, v, hv
    ORDER BY hv.createDate DESC
    LIMIT 1001
    WITH COLLECT({ru: ru, u: u, rvhv: rvhv, v: v, hv: hv}) AS data
    RETURN REDUCE(s = [], i IN RANGE(0, 1000, 100) | s + data[i]) AS result;
    
    • LIMIT 1001 子句将 data 集合的大小最小化为仅 1001 行数据(因为索引 1000 用于第 1001 行)。
    • RANGE(0, 1000, 100)用于生成感兴趣行的索引。
    • REDUCE 函数用于生成这些索引处的数据集合。