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
由于每次消费操作后总数据量增加,查询性能开始下降,延迟开始增加。
问题:
- 在某些时候,我的图表将包含超过 ~100k 值的历史节点,这会显着降低查询性能。因此,谁能建议更好的方法来存储或检索此类数据?
- 我不想一次发送所有存储的数据,而是希望能够根据从客户端收到的时间范围和确定要跳过到下一个元素的数量的步骤来限制 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只有百分之一的元素?有人知道怎么做吗?
因为你的查询在最后使用 ORDER BY
,Cypher 必须生成所有结果行,然后对它们进行排序。如果,如问题 #2 所述,您希望将结果限制在一个时间范围内,则应尽早对其进行过滤,以最大程度地减少工作量。例如,如果您只对参数化 startDate
和 endDate
值中的 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
除了执行上述早期过滤外,以下查询 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
函数用于生成这些索引处的数据集合。
应用背景: 我正在开发由客户端和服务器端组成的应用程序。服务器端每 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
由于每次消费操作后总数据量增加,查询性能开始下降,延迟开始增加。
问题:
- 在某些时候,我的图表将包含超过 ~100k 值的历史节点,这会显着降低查询性能。因此,谁能建议更好的方法来存储或检索此类数据?
- 我不想一次发送所有存储的数据,而是希望能够根据从客户端收到的时间范围和确定要跳过到下一个元素的数量的步骤来限制 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只有百分之一的元素?有人知道怎么做吗?
因为你的查询在最后使用
ORDER BY
,Cypher 必须生成所有结果行,然后对它们进行排序。如果,如问题 #2 所述,您希望将结果限制在一个时间范围内,则应尽早对其进行过滤,以最大程度地减少工作量。例如,如果您只对参数化startDate
和endDate
值中的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
除了执行上述早期过滤外,以下查询 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
函数用于生成这些索引处的数据集合。