Neo4j:更新Cypher查询以返回每百个元素

时间:2018-01-10 21:02:08

标签: neo4j cypher graph-databases

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

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

更多保存详情:每次,对于新消费的数据,我都会创建新的 历史值节点 ,并与现有的建立新的关系 (根)节点:

Data model

问题: 服务器端通过应用以下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. 我希望能够根据从客户端和步骤接收的时间范围来限制返回数据的大小,而不是一次发送所有存储的数据,这决定了要跳过的元素数量应该返回的下一个值。
  3. 例如:存储了1000个历史值节点。我想只返回每一百个元素,从第1个开始到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
    

    只返回每百个元素?有谁知道怎么做?

1 个答案:

答案 0 :(得分:3)

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

    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. 除了执行上述早期过滤之外,以下查询还返回索引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函数用于在这些索引处生成最终的数据集合。