From 4b649b86850f2f6b7d9e9d95291c80b754868085 Mon Sep 17 00:00:00 2001 From: Hieuzest Date: Thu, 22 Aug 2024 23:19:21 +0800 Subject: [PATCH] feat(minato): support logical exprs in querying to-many relation (#107) --- packages/core/src/database.ts | 6 +++++ packages/mongo/tests/migration.spec.ts | 13 +++++---- packages/tests/src/index.ts | 2 ++ packages/tests/src/relation.ts | 37 ++++++++++++++++++++++++++ yakumo.yml | 1 + 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/packages/core/src/database.ts b/packages/core/src/database.ts index b323dc06..4d0818a6 100644 --- a/packages/core/src/database.ts +++ b/packages/core/src/database.ts @@ -636,6 +636,9 @@ export class Database extends Servi )) } } else if (relation.type === 'oneToMany') { + if (query.$or) results.push(Eval.or(...query.$or.map((q: any) => this.transformRelationQuery(table, row, key, q).$expr))) + if (query.$and) results.push(...query.$and.map((q: any) => this.transformRelationQuery(table, row, key, q).$expr)) + if (query.$not) results.push(Eval.not(this.transformRelationQuery(table, row, key, query.$not).$expr)) if (query.$some) { results.push(Eval.in( relation.fields.map(x => row[x]), @@ -658,6 +661,9 @@ export class Database extends Servi const assocTable: any = Relation.buildAssociationTable(table, relation.table) const fields: any[] = relation.fields.map(x => Relation.buildAssociationKey(x, table)) const references = relation.references.map(x => Relation.buildAssociationKey(x, relation.table)) + if (query.$or) results.push(Eval.or(...query.$or.map((q: any) => this.transformRelationQuery(table, row, key, q).$expr))) + if (query.$and) results.push(...query.$and.map((q: any) => this.transformRelationQuery(table, row, key, q).$expr)) + if (query.$not) results.push(Eval.not(this.transformRelationQuery(table, row, key, query.$not).$expr)) if (query.$some) { const innerTable = this.select(relation.table, query.$some).evaluate(relation.references) const relTable = this.select(assocTable, r => Eval.in(references.map(x => r[x]), innerTable)).evaluate(fields) diff --git a/packages/mongo/tests/migration.spec.ts b/packages/mongo/tests/migration.spec.ts index 285176c0..0e9e761e 100644 --- a/packages/mongo/tests/migration.spec.ts +++ b/packages/mongo/tests/migration.spec.ts @@ -1,8 +1,7 @@ -import { $, Database, Primary } from 'minato' +import { $, Database, Driver, Primary } from 'minato' import { Context, ForkScope, Logger } from 'cordis' -import { expect } from 'chai' import MongoDriver from '@minatojs/driver-mongo' -import '@minatojs/tests' +import { expect } from '@minatojs/tests' const logger = new Logger('mongo') @@ -105,11 +104,11 @@ describe('@minatojs/driver-mongo/migrate-virtualKey', () => { await resetConfig(false) await expect(database.get('temp1', {})).to.eventually.deep.eq(table) - await (Object.values(database.drivers)[0] as MongoDriver).drop('_fields') + await (Object.values(database.drivers)[0] as Driver).drop('_fields') await resetConfig(true) await expect(database.get('temp1', {})).to.eventually.deep.eq(table) - await (Object.values(database.drivers)[0] as MongoDriver).drop('_fields') + await (Object.values(database.drivers)[0] as Driver).drop('_fields') await resetConfig(false) await expect(database.get('temp1', {})).to.eventually.deep.eq(table) }) @@ -139,11 +138,11 @@ describe('@minatojs/driver-mongo/migrate-virtualKey', () => { table.push(await database.create('temp2', { text: 'awesome baz' })) await expect(database.get('temp2', {})).to.eventually.deep.eq(table) - await (Object.values(database.drivers)[0] as MongoDriver).drop('_fields') + await (Object.values(database.drivers)[0] as Driver).drop('_fields') await resetConfig(true) await expect(database.get('temp2', {})).to.eventually.deep.eq(table) - await (Object.values(database.drivers)[0] as MongoDriver).drop('_fields') + await (Object.values(database.drivers)[0] as Driver).drop('_fields') await resetConfig(false) await expect(database.get('temp2', {})).to.eventually.deep.eq(table) diff --git a/packages/tests/src/index.ts b/packages/tests/src/index.ts index c5425317..957b822b 100644 --- a/packages/tests/src/index.ts +++ b/packages/tests/src/index.ts @@ -10,6 +10,8 @@ import Transaction from './transaction' import Relation from './relation' import './setup' +export { expect } from 'chai' + const Keywords = ['name'] type Keywords = 'name' diff --git a/packages/tests/src/relation.ts b/packages/tests/src/relation.ts index f2f7556e..ee90fd6b 100644 --- a/packages/tests/src/relation.ts +++ b/packages/tests/src/relation.ts @@ -452,6 +452,43 @@ namespace RelationTests { ...user, posts: posts.filter(post => post.author?.id === user.id), }))) + + await expect(database.get('user', { + posts: { + $or: [ + { + $some: { + author: { + id: 1, + }, + }, + }, + { + $none: { + author: {}, + }, + }, + ], + }, + })).to.eventually.have.shape([users[0], users[2]].map(user => ({ + ...user, + posts: posts.filter(post => post.author?.id === user.id), + }))) + + await expect(database.get('user', { + posts: { + $not: { + $some: { + author: { + id: 1, + }, + }, + }, + }, + })).to.eventually.have.shape([users[1], users[2]].map(user => ({ + ...user, + posts: posts.filter(post => post.author?.id === user.id), + }))) }) it('manyToMany', async () => { diff --git a/yakumo.yml b/yakumo.yml index c4fed37a..dfd5b637 100644 --- a/yakumo.yml +++ b/yakumo.yml @@ -6,6 +6,7 @@ - esbuild clean: - tsc --clean +- name: yakumo/run - name: yakumo-esbuild - name: yakumo-mocha - name: yakumo-tsc