Skip to content

Commit

Permalink
fix(mongo): support $regexFor operator
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jan 18, 2022
1 parent 0f031e3 commit 1829154
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
20 changes: 16 additions & 4 deletions packages/test-utils/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface Foo {
value?: number
list?: number[]
date?: Date
regex?: string
}

declare module 'koishi' {
Expand All @@ -22,6 +23,7 @@ function QueryOperators(app: App) {
value: 'integer',
list: 'list',
date: 'timestamp',
regex: 'string',
}, {
autoInc: true,
})
Expand Down Expand Up @@ -128,13 +130,23 @@ namespace QueryOperators {
}

export const regexp = function RegularExpression(app: App, options: RegExpOptions = {}) {
const { regexBy = true } = options
const { regexBy = true, regexFor = true } = options

before(async () => {
await app.database.remove('temp1', {})
await app.database.create('temp1', { text: 'awesome foo' })
await app.database.create('temp1', { text: 'awesome bar' })
await app.database.create('temp1', { text: 'awesome foo bar' })
await app.database.create('temp1', { text: 'awesome foo', regex: 'foo' })
await app.database.create('temp1', { text: 'awesome bar', regex: 'bar' })
await app.database.create('temp1', { text: 'awesome foo bar', regex: 'baz' })
})

regexFor && it('$regexFor', async () => {
await expect(app.database.get('temp1', {
regex: { $regexFor: 'foo bar' },
})).eventually.to.have.length(2)

await expect(app.database.get('temp1', {
regex: { $regexFor: 'baz' },
})).eventually.to.have.length(1)
})

regexBy && it('$regexBy', async () => {
Expand Down
31 changes: 20 additions & 11 deletions plugins/database/mongo/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Query, Random, valueMap } from 'koishi'
import { Filter, FilterOperators } from 'mongodb'

function transformFieldQuery(query: Query.FieldQuery, key: string) {
function transformFieldQuery(query: Query.FieldQuery, key: string, exprs: any[]) {
// shorthand syntax
if (typeof query === 'string' || typeof query === 'number' || query instanceof Date) {
return { $eq: query }
Expand All @@ -16,15 +16,17 @@ function transformFieldQuery(query: Query.FieldQuery, key: string) {
const result: FilterOperators<any> = {}
for (const prop in query) {
if (prop === '$el') {
result.$elemMatch = transformFieldQuery(query[prop], key)
result.$elemMatch = transformFieldQuery(query[prop], key, exprs)
} else if (prop === '$regexFor') {
result.$expr = {
body(data: string, value: string) {
return new RegExp(data, 'i').test(value)
exprs.push({
$function: {
body: function (data: string, value: string) {
return new RegExp(data, 'i').test(value)
}.toString(),
args: ['$' + key, query.$regexFor],
lang: 'js',
},
args: ['$' + key, query],
lang: 'js',
}
})
} else {
result[prop] = query[prop]
}
Expand All @@ -34,6 +36,7 @@ function transformFieldQuery(query: Query.FieldQuery, key: string) {

export function transformQuery(query: Query.Expr) {
const filter: Filter<any> = {}
const exprs: any[] = []
for (const key in query) {
const value = query[key]
if (key === '$and' || key === '$or') {
Expand All @@ -49,13 +52,19 @@ export function transformQuery(query: Query.Expr) {
// MongoError: unknown top level operator: $not
// https://stackoverflow.com/questions/25270396/mongodb-how-to-invert-query-with-not
// this may solve this problem but lead to performance degradation
filter.$nor = [transformQuery(value)]
const query = transformQuery(value)
if (query) filter.$nor = [query]
} else if (key === '$expr') {
filter[key] = transformEval(value)
exprs.push(transformEval(value))
} else {
filter[key] = transformFieldQuery(value, key)
const query = transformFieldQuery(value, key, exprs)
if (!query) return
if (Object.keys(query).length) filter[key] = query
}
}
if (exprs.length) {
(filter.$and ||= []).push(...exprs.map($expr => ({ $expr })))
}
return filter
}

Expand Down

0 comments on commit 1829154

Please sign in to comment.