From 5da7eeaae579fba30b82b9ce29959fb8d1dc2536 Mon Sep 17 00:00:00 2001 From: kitsunecafe Date: Wed, 20 Nov 2024 13:17:53 -0600 Subject: [PATCH] initial query engine workinggit status \o/ --- src/query.js | 46 +++++++++++++++++++++++++++++++++++++-------- tests/query.test.js | 10 +++------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/query.js b/src/query.js index 958d608..f12fbec 100644 --- a/src/query.js +++ b/src/query.js @@ -70,10 +70,10 @@ const cat = flip(concat) const executeQuery = (query, world) => { if (!query.relationship) { - return map(of, query.query(world)) + return map(id => ({ [id]: query }), query.query(world)) } - const { from, to: _to, edge, returnValues } = query + const { from, to: _to, edge } = query const to = getEndNode(_to) const Edge = edge.type @@ -85,7 +85,6 @@ const executeQuery = (query, world) => { world ) - if (_to.relationship) { return reduce((acc, eid) => { const next = { @@ -97,22 +96,53 @@ const executeQuery = (query, world) => { } const results = map(cat([eid]), executeQuery(next, world)) - return [...acc, ...results] + const expanded = map( + ([l, r]) => ({ [l]: query, ...r }), + results + ) + return [...acc, ...expanded] }, [], edges) } else { - return map(of, edges) + return map(id => of({ [id]: query }), edges) } } +const val = v => v?.value?.value +const include = returns => name => name != null && returns.includes(name) + +const resolveReturns = results => { + return map(result => { + return reduce((acc, [id, query]) => { + const q = query.schema.match + const inc = include(query.schema.returnValues.values.map(x => x.value)) + if (is(Relationship, q)) { + const Edge = query.edge.type + const fn = val(q.from.name) + const en = val(q.edge.name) + const tn = val(q.to.name) + return { + ...acc, ...{ + ...(inc(fn) && { [fn]: Edge.from[id] }), + ...(inc(en) && { [en]: parseInt(id, 10) }), + ...(inc(tn) && { [tn]: Edge.to[id] }) + } + } + } else { + const name = val(q.name) + return { ...acc, ...(inc(name) && { [name]: id }) } + } + }, {}, Object.entries(result)) + }, results) +} + export const query = curry((input, engine) => { return parseAll(q, input).map(({ use, ...rest }) => { const worldName = use && use.value || 'default' const world = engine.world[worldName] const prepared = prepareQuery(rest, engine.component) - const results = executeQuery(prepared, world) - // TODO: handle return value mapping - return results + const edges = executeQuery(prepared, world) + return resolveReturns(edges) }) }) diff --git a/tests/query.test.js b/tests/query.test.js index c27106f..cc71517 100644 --- a/tests/query.test.js +++ b/tests/query.test.js @@ -41,10 +41,6 @@ describe('query', () => { const a = create(NPC) // 1 const b = create(NPC) // 2 const c = create(NPC) // 3 - //const d = create(NPC) - //const e = create(NPC) - //const f = create(NPC) - //const g = create(NPC) knows(player, a) // 4 knows(player, c) // 5 @@ -56,10 +52,10 @@ describe('query', () => { knows(b, a) // 9 knows(c, player) // 10 - //knows(c, b) // 11 - const result = query('MATCH (player:NPC) RETURN player, a, b', engine) - console.log(result.unwrap()) + const q = 'MATCH (player:Player)-[e1:Knows]->(a:NPC)-[e2:Knows]->(b:NPC) RETURN player, e1, a, e2, b' + const result = query(q, engine) + console.log(`parsing ${q}\n`, result.unwrap()) }) })