【问题标题】:Neo4j: update Cypher query to return every hundredth elementNeo4j:更新 Cypher 查询以返回每百分之一的元素
【发布时间】:2018-01-10 21:02:07
【问题描述】:

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

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

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

问题: 服务器端通过应用以下 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. 不是一次发送所有存储的数据,我希望能够根据从客户端接收的时间范围和步骤来限制返回数据的大小,该步骤确定要跳到下一个应该返回的值的元素数量。

例如:存储了 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

只返回每百分之一的元素?有人知道怎么做吗?

【问题讨论】:

    标签: neo4j cypher graph-databases


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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 2017-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多