Я хочу определить свои запросы Neo4j с точки зрения общей структуры (во многом похожей на GraphQL) и составить их. Например, вот простой запрос без композиции:
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-запросе. Возможно, потребуется некоторый анализ вывода, но в идеале я также получу сопоставимую структуру данных в качестве вывода.
Любые идеи?