mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-22 08:20:39 +00:00
add gt lt query (#1415)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
parent
5f374c293b
commit
0dcdc19021
@ -36,13 +36,15 @@ class ClientModel extends ModelDb implements Client {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne<T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>): Promise<WithLookup<T> | undefined> {
|
async findOne<T extends Doc>(
|
||||||
|
_class: Ref<Class<T>>,
|
||||||
|
query: DocumentQuery<T>,
|
||||||
|
options?: FindOptions<T>
|
||||||
|
): Promise<WithLookup<T> | undefined> {
|
||||||
return (await this.findAll(_class, query, options)).shift()
|
return (await this.findAll(_class, query, options)).shift()
|
||||||
}
|
}
|
||||||
|
|
||||||
async close (): Promise<void> {
|
async close (): Promise<void> {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createModel (): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
|
async function createModel (): Promise<{ model: ClientModel, hierarchy: Hierarchy, txDb: TxDb }> {
|
||||||
@ -84,7 +86,13 @@ describe('memdb', () => {
|
|||||||
const result2 = await client.findAll(core.class.Space, {})
|
const result2 = await client.findAll(core.class.Space, {})
|
||||||
expect(result2).toHaveLength(3)
|
expect(result2).toHaveLength(3)
|
||||||
|
|
||||||
await client.createDoc(core.class.Space, core.space.Model, { private: false, name: 'NewSpace', description: '', members: [], archived: false })
|
await client.createDoc(core.class.Space, core.space.Model, {
|
||||||
|
private: false,
|
||||||
|
name: 'NewSpace',
|
||||||
|
description: '',
|
||||||
|
members: [],
|
||||||
|
archived: false
|
||||||
|
})
|
||||||
const result3 = await client.findAll(core.class.Space, {})
|
const result3 = await client.findAll(core.class.Space, {})
|
||||||
expect(result3).toHaveLength(4)
|
expect(result3).toHaveLength(4)
|
||||||
})
|
})
|
||||||
@ -92,7 +100,7 @@ describe('memdb', () => {
|
|||||||
it('should query model', async () => {
|
it('should query model', async () => {
|
||||||
const { model } = await createModel()
|
const { model } = await createModel()
|
||||||
const result = await model.findAll(core.class.Class, {})
|
const result = await model.findAll(core.class.Class, {})
|
||||||
const names = result.map(d => d._id)
|
const names = result.map((d) => d._id)
|
||||||
expect(names.includes(core.class.Class)).toBe(true)
|
expect(names.includes(core.class.Class)).toBe(true)
|
||||||
const result2 = await model.findAll(core.class.Class, { _id: undefined })
|
const result2 = await model.findAll(core.class.Class, { _id: undefined })
|
||||||
expect(result2.length).toBe(0)
|
expect(result2.length).toBe(0)
|
||||||
@ -108,7 +116,9 @@ describe('memdb', () => {
|
|||||||
const { model } = await createModel()
|
const { model } = await createModel()
|
||||||
const ops = new TxOperations(model, core.account.System)
|
const ops = new TxOperations(model, core.account.System)
|
||||||
|
|
||||||
await ops.createMixin<Doc, TestMixin>(core.class.Obj, core.class.Class, core.space.Model, test.mixin.TestMixin, { arr: ['hello'] })
|
await ops.createMixin<Doc, TestMixin>(core.class.Obj, core.class.Class, core.space.Model, test.mixin.TestMixin, {
|
||||||
|
arr: ['hello']
|
||||||
|
})
|
||||||
const objClass = (await model.findAll(core.class.Class, { _id: core.class.Obj }))[0] as any
|
const objClass = (await model.findAll(core.class.Class, { _id: core.class.Obj }))[0] as any
|
||||||
expect(objClass['test:mixin:TestMixin'].arr).toEqual(expect.arrayContaining(['hello']))
|
expect(objClass['test:mixin:TestMixin'].arr).toEqual(expect.arrayContaining(['hello']))
|
||||||
|
|
||||||
@ -160,6 +170,24 @@ describe('memdb', () => {
|
|||||||
space: { $in: [core.space.Model, core.space.Tx] }
|
space: { $in: [core.space.Model, core.space.Tx] }
|
||||||
})
|
})
|
||||||
expect(multipleParam.length).toBeGreaterThan(5)
|
expect(multipleParam.length).toBeGreaterThan(5)
|
||||||
|
|
||||||
|
const classes = await model.findAll(core.class.Class, {})
|
||||||
|
const gt = await model.findAll(core.class.Class, {
|
||||||
|
kind: { $gt: 1 }
|
||||||
|
})
|
||||||
|
expect(gt.length).toBe(classes.filter((p) => p.kind > 1).length)
|
||||||
|
const gte = await model.findAll(core.class.Class, {
|
||||||
|
kind: { $gte: 1 }
|
||||||
|
})
|
||||||
|
expect(gte.length).toBe(classes.filter((p) => p.kind >= 1).length)
|
||||||
|
const lt = await model.findAll(core.class.Class, {
|
||||||
|
kind: { $lt: 1 }
|
||||||
|
})
|
||||||
|
expect(lt.length).toBe(classes.filter((p) => p.kind < 1).length)
|
||||||
|
const lte = await model.findAll(core.class.Class, {
|
||||||
|
kind: { $lt: 1 }
|
||||||
|
})
|
||||||
|
expect(lte.length).toBe(classes.filter((p) => p.kind <= 1).length)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should query model like params', async () => {
|
it('should query model like params', async () => {
|
||||||
@ -260,25 +288,51 @@ describe('memdb', () => {
|
|||||||
const spaces = await client.findAll(core.class.Space, {})
|
const spaces = await client.findAll(core.class.Space, {})
|
||||||
expect(spaces).toHaveLength(2)
|
expect(spaces).toHaveLength(2)
|
||||||
|
|
||||||
const first = await client.addCollection(test.class.TestComment, core.space.Model, spaces[0]._id, spaces[0]._class, 'comments', {
|
const first = await client.addCollection(
|
||||||
message: 'msg'
|
test.class.TestComment,
|
||||||
})
|
core.space.Model,
|
||||||
|
spaces[0]._id,
|
||||||
|
spaces[0]._class,
|
||||||
|
'comments',
|
||||||
|
{
|
||||||
|
message: 'msg'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const second = await client.addCollection(test.class.TestComment, core.space.Model, first, test.class.TestComment, 'comments', {
|
const second = await client.addCollection(
|
||||||
message: 'msg2'
|
test.class.TestComment,
|
||||||
})
|
core.space.Model,
|
||||||
|
first,
|
||||||
|
test.class.TestComment,
|
||||||
|
'comments',
|
||||||
|
{
|
||||||
|
message: 'msg2'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
await client.addCollection(test.class.TestComment, core.space.Model, spaces[0]._id, spaces[0]._class, 'comments', {
|
await client.addCollection(test.class.TestComment, core.space.Model, spaces[0]._id, spaces[0]._class, 'comments', {
|
||||||
message: 'msg3'
|
message: 'msg3'
|
||||||
})
|
})
|
||||||
|
|
||||||
const simple = await client.findAll(test.class.TestComment, { _id: first }, { lookup: { attachedTo: spaces[0]._class } })
|
const simple = await client.findAll(
|
||||||
|
test.class.TestComment,
|
||||||
|
{ _id: first },
|
||||||
|
{ lookup: { attachedTo: spaces[0]._class } }
|
||||||
|
)
|
||||||
expect(simple[0].$lookup?.attachedTo).toEqual(spaces[0])
|
expect(simple[0].$lookup?.attachedTo).toEqual(spaces[0])
|
||||||
|
|
||||||
const nested = await client.findAll(test.class.TestComment, { _id: second }, { lookup: { attachedTo: [test.class.TestComment, { attachedTo: spaces[0]._class } as any] } })
|
const nested = await client.findAll(
|
||||||
|
test.class.TestComment,
|
||||||
|
{ _id: second },
|
||||||
|
{ lookup: { attachedTo: [test.class.TestComment, { attachedTo: spaces[0]._class } as any] } }
|
||||||
|
)
|
||||||
expect((nested[0].$lookup?.attachedTo as any).$lookup?.attachedTo).toEqual(spaces[0])
|
expect((nested[0].$lookup?.attachedTo as any).$lookup?.attachedTo).toEqual(spaces[0])
|
||||||
|
|
||||||
const reverse = await client.findAll(spaces[0]._class, { _id: spaces[0]._id }, { lookup: { _id: { comments: test.class.TestComment } } })
|
const reverse = await client.findAll(
|
||||||
|
spaces[0]._class,
|
||||||
|
{ _id: spaces[0]._id },
|
||||||
|
{ lookup: { _id: { comments: test.class.TestComment } } }
|
||||||
|
)
|
||||||
expect((reverse[0].$lookup as any).comments).toHaveLength(2)
|
expect((reverse[0].$lookup as any).comments).toHaveLength(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -306,7 +360,11 @@ describe('memdb', () => {
|
|||||||
text: 'qwe2'
|
text: 'qwe2'
|
||||||
})
|
})
|
||||||
|
|
||||||
const results = await client.findAll(test.class.TestMixinTodo, {}, { lookup: { attachedTo: test.mixin.TaskMixinTodos } })
|
const results = await client.findAll(
|
||||||
|
test.class.TestMixinTodo,
|
||||||
|
{},
|
||||||
|
{ lookup: { attachedTo: test.mixin.TaskMixinTodos } }
|
||||||
|
)
|
||||||
expect(results.length).toEqual(2)
|
expect(results.length).toEqual(2)
|
||||||
const attached = results[0].$lookup?.attachedTo
|
const attached = results[0].$lookup?.attachedTo
|
||||||
expect(attached).toBeDefined()
|
expect(attached).toBeDefined()
|
||||||
|
@ -49,7 +49,10 @@ const predicates: Record<string, PredicateFactory> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
$like: (query: string, propertyKey: string): Predicate => {
|
$like: (query: string, propertyKey: string): Predicate => {
|
||||||
const searchString = query.split('%').map(it => escapeLikeForRegexp(it)).join('.*')
|
const searchString = query
|
||||||
|
.split('%')
|
||||||
|
.map((it) => escapeLikeForRegexp(it))
|
||||||
|
.join('.*')
|
||||||
const regex = RegExp(`^${searchString}$`, 'i')
|
const regex = RegExp(`^${searchString}$`, 'i')
|
||||||
|
|
||||||
return (docs) => execPredicate(docs, propertyKey, (value) => regex.test(value))
|
return (docs) => execPredicate(docs, propertyKey, (value) => regex.test(value))
|
||||||
@ -58,11 +61,25 @@ const predicates: Record<string, PredicateFactory> = {
|
|||||||
$regex: (o: { $regex: string, $options: string }, propertyKey: string): Predicate => {
|
$regex: (o: { $regex: string, $options: string }, propertyKey: string): Predicate => {
|
||||||
const re = new RegExp(o.$regex, o.$options)
|
const re = new RegExp(o.$regex, o.$options)
|
||||||
return (docs) => execPredicate(docs, propertyKey, (value) => value.match(re) !== null)
|
return (docs) => execPredicate(docs, propertyKey, (value) => value.match(re) !== null)
|
||||||
|
},
|
||||||
|
$gt: (o, propertyKey) => {
|
||||||
|
return (docs) => execPredicate(docs, propertyKey, (value) => value > o)
|
||||||
|
},
|
||||||
|
$gte: (o, propertyKey) => {
|
||||||
|
return (docs) => execPredicate(docs, propertyKey, (value) => value >= o)
|
||||||
|
},
|
||||||
|
$lt: (o, propertyKey) => {
|
||||||
|
return (docs) => execPredicate(docs, propertyKey, (value) => value < o)
|
||||||
|
},
|
||||||
|
$lte: (o, propertyKey) => {
|
||||||
|
return (docs) => execPredicate(docs, propertyKey, (value) => value <= o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPredicate (o: Record<string, any>): boolean {
|
export function isPredicate (o: Record<string, any>): boolean {
|
||||||
if (o === null || typeof o !== 'object') { return false }
|
if (o === null || typeof o !== 'object') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
const keys = Object.keys(o)
|
const keys = Object.keys(o)
|
||||||
return keys.length > 0 && keys.every((key) => key.startsWith('$'))
|
return keys.length > 0 && keys.every((key) => key.startsWith('$'))
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,10 @@ import type { Tx } from './tx'
|
|||||||
export type QuerySelector<T> = {
|
export type QuerySelector<T> = {
|
||||||
$in?: T[]
|
$in?: T[]
|
||||||
$nin?: T[]
|
$nin?: T[]
|
||||||
|
$gt?: T extends number ? number : never
|
||||||
|
$gte?: T extends number ? number : never
|
||||||
|
$lt?: T extends number ? number : never
|
||||||
|
$lte?: T extends number ? number : never
|
||||||
$like?: string
|
$like?: string
|
||||||
$regex?: string
|
$regex?: string
|
||||||
$options?: string
|
$options?: string
|
||||||
@ -49,11 +53,15 @@ export type DocumentQuery<T extends Doc> = {
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export type ToClassRefT<T extends object, P extends keyof T> = T[P] extends Ref<infer X> | null | undefined ? Ref<Class<X>> | [Ref<Class<X>>, Lookup<X>] : never
|
export type ToClassRefT<T extends object, P extends keyof T> = T[P] extends Ref<infer X> | null | undefined
|
||||||
|
? Ref<Class<X>> | [Ref<Class<X>>, Lookup<X>]
|
||||||
|
: never
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export type ToClassRefTA<T extends object, P extends keyof T> = T[P] extends Array<Ref<infer X>> | null | undefined ? Ref<Class<X>> | [Ref<Class<X>>, Lookup<X>] : never
|
export type ToClassRefTA<T extends object, P extends keyof T> = T[P] extends Array<Ref<infer X>> | null | undefined
|
||||||
|
? Ref<Class<X>> | [Ref<Class<X>>, Lookup<X>]
|
||||||
|
: never
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user