Neo4j Cypher具有超限制模式理解能力——还是我用错了?
我最近选择了Neo4j,因为它似乎是存储数据的最佳数据库类型,我目前正在从一些在线论坛上搜集数据。图的主要结构是社区->论坛->线程->帖子->作者 我正在尝试编写Cypher查询来解析GraphQL查询,并希望对论坛->线程连接进行分页(例如)。关系是CONTAINS,它持有一个Neo4j Cypher具有超限制模式理解能力——还是我用错了?,neo4j,graphql,cypher,Neo4j,Graphql,Cypher,我最近选择了Neo4j,因为它似乎是存储数据的最佳数据库类型,我目前正在从一些在线论坛上搜集数据。图的主要结构是社区->论坛->线程->帖子->作者 我正在尝试编写Cypher查询来解析GraphQL查询,并希望对论坛->线程连接进行分页(例如)。关系是CONTAINS,它持有一个顺序属性,即(f:Forum)-[:CONTAINS]->(t:Thread) 从neo4j graphql js库中,我了解了他们使用模式理解在子节点上运行“内部查询”的方法。例如: MATCH (f:Forum {
顺序
属性,即(f:Forum)-[:CONTAINS]->(t:Thread)
从neo4j graphql js库中,我了解了他们使用模式理解在子节点上运行“内部查询”的方法。例如:
MATCH (f:Forum { id: $id })
RETURN f { .id, .name, .url, threads: [(f)-[:CONTAINS]->(t:Thread) | t { .id, .title, .url }] }
我真的很想在内部模式理解上使用ORDER BY,LIMIT和SKIP,但不幸的是,这是不受支持的:-neo4j graphql js库通过使用apoc.coll.sortMulti
解决了这个问题,但我注意到性能不是很好&比在顶级模式上使用ORDER by子句慢得多
由于我是graph DBMS的新手,这让我想知道我是否误解了graph DB应该如何使用。从“frontender”的角度来看,在最低级别的查询语言中实现分页的能力似乎是一个关键部分,但同样,也许我没有正确理解。方钉、圆孔等等
这是一个公平的评价吗?Cypher中是否有其他解决方案?或者,我应该回到使用SQL数据库来处理这个用例吗?[编辑]
如果将order
属性移动到Thread
节点中(如果每个Thread
节点仅连接到一个论坛
,则该属性应有效),则可以在:Thread(order)
上创建(或)以加快查询速度
例如,此查询应利用索引更快地向前分页(假设用于分页目的的f.id
、order
值和limit
值作为id
、order
和limit
传递):
下面是一个(稍微复杂一些,但也很快)向后分页查询:
MATCH (f:Forum)-[:CONTAINS]->(t:Thread)
WHERE f.id = $id AND t.order < $order
WITH f, t
ORDER BY t.order DESC
LIMIT $limit
WITH f, t
ORDER BY t.order
RETURN f{.id, .name, .URL,
firstOrder: MIN(t.order),
lastOrder: MAX(t.order),
threads: [x IN COLLECT(t) | x{.id, .title, .URL}]}
Brilliant@cybersam-你知道Cypher规范的哪一部分确保内部
收集每个论坛只收集正确的线程吗?我删除了WHERE子句并运行了查询,令我惊讶的是,它没有为每个结果收集相同的线程集,而是对每个论坛进行了分区。我不确定我是否解释得很好,但与此相反,如果collect()在“f{…}”扩展之外,它会从任何地方收集所有线程,对吗?而且很遗憾,您不能在关系属性上建立索引。我无法移动order属性,因为其他节点的线程的其他列表视图也需要关系上的order属性。您知道是否真的没有办法提高关系属性的排序性能,或者管道中的任何东西可以解决这个问题吗?不清楚为什么关系上确实需要order
节点。你是说一个线程
节点可以有多个包含
关系,或者类似的东西?总之,wrtCOLLECT
,阅读他们如何使用“分组键”--您看到的结果正是经过调整的查询应该发生的结果。我刚刚调整了我的答案,以提供向前和向后分页的查询。您可以查看,它们确实支持关系索引,但它们使用字符串属性,并且也需要您付出更多的努力。
MATCH (f:Forum)-[:CONTAINS]->(t:Thread)
WHERE f.id = $id AND t.order < $order
WITH f, t
ORDER BY t.order DESC
LIMIT $limit
WITH f, t
ORDER BY t.order
RETURN f{.id, .name, .URL,
firstOrder: MIN(t.order),
lastOrder: MAX(t.order),
threads: [x IN COLLECT(t) | x{.id, .title, .URL}]}
F*L << (average number of `Threads` per `Forum`).