Neo4j Cypher具有超限制模式理解能力——还是我用错了?

Neo4j Cypher具有超限制模式理解能力——还是我用错了?,neo4j,graphql,cypher,Neo4j,Graphql,Cypher,我最近选择了Neo4j,因为它似乎是存储数据的最佳数据库类型,我目前正在从一些在线论坛上搜集数据。图的主要结构是社区->论坛->线程->帖子->作者 我正在尝试编写Cypher查询来解析GraphQL查询,并希望对论坛->线程连接进行分页(例如)。关系是CONTAINS,它持有一个顺序属性,即(f:Forum)-[:CONTAINS]->(t:Thread) 从neo4j graphql js库中,我了解了他们使用模式理解在子节点上运行“内部查询”的方法。例如: MATCH (f:Forum {

我最近选择了Neo4j,因为它似乎是存储数据的最佳数据库类型,我目前正在从一些在线论坛上搜集数据。图的主要结构是社区->论坛->线程->帖子->作者

我正在尝试编写Cypher查询来解析GraphQL查询,并希望对论坛->线程连接进行分页(例如)。关系是CONTAINS,它持有一个
顺序
属性,即
(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
节点。你是说一个
线程
节点可以有多个
包含
关系,或者类似的东西?总之,wrt
COLLECT
,阅读他们如何使用“分组键”--您看到的结果正是经过调整的查询应该发生的结果。我刚刚调整了我的答案,以提供向前和向后分页的查询。您可以查看,它们确实支持关系索引,但它们使用字符串属性,并且也需要您付出更多的努力。
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`).