UBERF-7543: Add low level groupBy api and improve security space lookup (#6126)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2024-07-28 14:55:42 +07:00
committed by Andrey Sobolev
parent 3bec396384
commit aa1bbd6247
12 changed files with 130 additions and 34 deletions
+84 -10
View File
@@ -82,7 +82,8 @@ import {
type Filter,
type FindCursor,
type Sort,
type UpdateFilter
type UpdateFilter,
type FindOptions as MongoFindOptions
} from 'mongodb'
import { DBCollectionHelper, getMongoClient, getWorkspaceDB, type MongoClientReference } from './utils'
@@ -517,10 +518,18 @@ abstract class MongoAdapterBase implements DbAdapter {
let result: WithLookup<T>[] = []
let total = options?.total === true ? 0 : -1
try {
result = await ctx.with('toArray', {}, async (ctx) => await toArray(cursor), {
domain,
pipeline
})
await ctx.with(
'toArray',
{},
async (ctx) => {
result = await toArray(cursor)
},
() => ({
size: result.length,
domain,
pipeline
})
)
} catch (e) {
console.error('error during executing cursor in findWithPipeline', clazz, cutObjectArray(query), options, e)
throw e
@@ -623,6 +632,33 @@ abstract class MongoAdapterBase implements DbAdapter {
return false
}
@withContext('groupBy')
async groupBy<T>(ctx: MeasureContext, domain: Domain, field: string): Promise<Set<T>> {
const result = await this.globalCtx.with(
'groupBy',
{ domain },
async (ctx) => {
const coll = this.collection(domain)
const grResult = await coll
.aggregate([
{
$group: {
_id: '$' + field
}
}
])
.toArray()
return new Set(grResult.map((it) => it._id as unknown as T))
},
() => ({
findOps: this.findOps,
txOps: this.txOps
})
)
return result
}
findOps: number = 0
txOps: number = 0
opIndex: number = 0
@@ -695,6 +731,33 @@ abstract class MongoAdapterBase implements DbAdapter {
const coll = this.collection(domain)
const mongoQuery = this.translateQuery(_class, query)
if (options?.limit === 1) {
// Skip sort/projection/etc.
return await ctx.with(
'find-one',
{},
async (ctx) => {
const findOptions: MongoFindOptions = {}
if (options?.sort !== undefined) {
findOptions.sort = this.collectSort<T>(options, _class)
}
if (options?.projection !== undefined) {
findOptions.projection = this.calcProjection<T>(options, _class)
} else {
findOptions.projection = { '%hash%': 0 }
}
const doc = await coll.findOne(mongoQuery, findOptions)
if (doc != null) {
return toFindResult([doc as unknown as T])
}
return toFindResult([])
},
{ mongoQuery }
)
}
let cursor = coll.find<T>(mongoQuery)
if (options?.projection !== undefined) {
@@ -702,6 +765,8 @@ abstract class MongoAdapterBase implements DbAdapter {
if (projection != null) {
cursor = cursor.project(projection)
}
} else {
cursor = cursor.project({ '%hash%': 0 })
}
let total: number = -1
if (options != null) {
@@ -721,11 +786,20 @@ abstract class MongoAdapterBase implements DbAdapter {
// Error in case of timeout
try {
const res: T[] = await ctx.with('toArray', {}, async (ctx) => await toArray(cursor), {
mongoQuery,
options,
domain
})
let res: T[] = []
await ctx.with(
'toArray',
{},
async (ctx) => {
res = await toArray(cursor)
},
() => ({
size: res.length,
mongoQuery,
options,
domain
})
)
if (options?.total === true && options?.limit === undefined) {
total = res.length
}