我想根据通用结构(很像GraphQL)定义我的Neo4j查询并组合它们。 例如,这是一个没有组合的简单查询:
chatrooms: {
query: {limit: 10}
fields: {
id: true,
name: true }}
我的Neo4j翻译可能如下所示:
chatrooms = ({query, fields}) ->
"""
MATCH (c:CHATROOMS)
RETURN #{R.join(' ', R.map(R.concat('c.'), R.keys(fields)))}
LIMIT #{query.limit}
"""
但是当我想要构建更深层次的嵌套查询时,我遇到了麻烦。 例如,如果我想要一些关于每个聊天室所有者的信息怎么办?我应该能够一次查询所有这些,而不是花费两次往返HTTP请求。
chatrooms: {
query: {limit: 10}
fields: {
id: true,
name: true
owner: {
fields: {
id: true,
name: true}}}}
此时,我有点挂了。 我不知道如何使解释器足够通用以处理这些情况。 我知道查询看起来应该是这样的。
MATCH (c:CHATROOM)
MATCH (c)<-[:OWNS]-(u:USER)
RETURN c.id, c.name, u.id, u.name
LIMIT 10
理想情况下,此查询将返回具有类似结构的内容:
[
{id: 1, name:'neo4j', owner: {id: 99, name: 'michael'}}
{id: 2, name:'meteor', owner: {id: 100, name: 'chet'}}
]
这样可以使结果的组合和解释变得更加容易,但这是后来的细节。
最后,我无法更深入地嵌套这些查询。 例如,如果我还想为每个聊天室添加一些消息,该怎么办? 如果我想了解每个聊天室所有者的一些信息怎么办?
chatrooms: {
query: {limit: 10}
fields: {
id: true,
name: true
owner: {
fields: {
id: true,
name: true}}
messages: {
query: {limit: 20}
fields: {
id: true,
text: true,
createdAt: true,
owner: {
fields: {
id: true,
name: true }}}}}}
这是我的理由 - 虽然我很确定它是完全错误的。
MATCH (c:CHATROOM)
MATCH (c)<-[:OWNS]-(u:USER)
UNWIND c as room
MATCH (room)-[:OWNS]->(m:MESSAGE)
MATCH (m)<-[:OWNS]-(x:USER)
RETURN collect(m.id, m.text, m.creatdAt, x.id, x.name)
LIMIT 20
RETURN c.id, c.name, u.id, u.name,
LIMIT 10
无论如何,目标是能够指定一个巨大的嵌套查询,并能够在一个HTTP请求中运行它。 也许有必要对输出进行一些解析,但理想情况下,我将获得与输出相当的数据结构。
有什么想法吗?
答案 0 :(得分:1)
首先,GraphQL哲学还有嵌套结构。
您应该使用引用。
e.g。
chatrooms: {
query: {limit: 10}
fields: {
id: true,
name: true
owner: ${owner.id}
messages: {
query: {limit: 20}
fields: {
id: true,
text: true,
createdAt: true,
owner: ${owner.id}
}
}
}
owners: [{id: 1, fields: { id: true, name: true}}]
为什么在根对象中使用fields属性而不是字段?
答案 1 :(得分:1)
您可以使用collect({key:value})
或{key:collect(value)
的序列和组合。
MATCH (c:CHATROOM)<-[:OWNS]-(u:USER)
RETURN {id: c.id, name: c.name, owner: collect({id: u.id, name: u.name})} AS data
LIMIT 10
然后使用这些数据:
create (c:CHATROOM {id:1, name:"neo4j"})<-[:OWNS]-(u:USER {id:99,name:"Michael")
create (c:CHATROOM {id:2, name:"meteor"})<-[:OWNS]-(u:USER {id:100,name:"Chet")
运行你得到的查询
+--------------------------------------------------------------------+
| data |
+--------------------------------------------------------------------+
| {id=2, name=meteor, owner=[{id=100, name=Chet}]} |
| {id=1, name=neo4j, owner=[{id=99, name=Michael}]} |
+--------------------------------------------------------------------+
住在这里:http://console.neo4j.org/r/d41luc
要将两个行合并为一个,您可以使用WITH
然后使用RETURN
,但之后您将无法获得将数据流式传输回来的好处。
MATCH (c:CHATROOM)<-[:OWNS]-(u:USER)
WITH {id: c.id, name: c.name, owner: collect({id: u.id, name: u.name})} AS row
RETURN collect(row) as data
LIMIT 10
请使用更具描述性的关系类型,而不仅仅是:OWNS
。
MATCH (c:CHATROOM)<-[:OWNS]-(u:USER)
MATCH (c)-[:OWNS]->(m:MESSAGE)<-[:OWNS]-(x:USER)
WITH u,c,collect({id: m.id, text: m.text, created_at: m.createdAt, author_id: x.id, author: x.name}) as messages[0..20]
RETURN collect({ id: c.id, room: c.name,
owner_id: u.id, owner: u.name,
messages: messages}) as rooms
LIMIT 10