I mean, which is faster / more efficient / or easier to go wrong?
Of course, Promises to query for _id
are more TypeScript-friendly.
export function getAuthorizedCategories(o: {
userId: string
type?: typeof sDictionaryType.type | 'user' | typeof sDictionaryType.type[]
langFrom?: 'chinese'
langTo?: string
_id?: string
}) {
return DbCategoryModel.find({
_id: o._id,
userId: {
$in: [o.userId, 'shared', 'default'],
},
type: o.type
? o.type === 'user'
? { $exists: false }
: Array.isArray(o.type)
? { $in: o.type }
: o.type
: undefined,
langFrom: o.langFrom,
langTo: o.langTo as 'english',
})
}
function _doSearch({
userId,
type,
langFrom,
langTo,
q,
page,
perPage,
limit,
select,
exclude,
randomize,
}: Parameters<typeof getAuthorizedCategories>[0] & {
q?: string
page?: number
perPage?: number
limit: number
select: string[]
exclude?: string[]
randomize?: {
levelMin: number
levelMax: number
}
}) {
return (async () => {
let cursor = getAuthorizedCategories({
userId,
type,
langFrom,
langTo,
})
if (!randomize) {
cursor = cursor.sort('-priority')
}
return cursor.select('_id')
})().then((cs) => {
if (cs.length) {
return Promise.all(
cs.map(async (c) => {
let cursor = DbItemModel.find({
$and: [
q ? { $text: { $search: q, $language: langFrom } } : null,
{ categoryId: c._id },
{ entry: exclude ? { $nin: exclude } : undefined },
]
.filter((el) => el)
.map((el) => el!),
})
if (!randomize) {
cursor = cursor.sort('-priority -level')
}
return cursor.select('_id').then((its) => ({
itemIds: its.map((it) => it._id),
}))
})
).then(async (cs) => {
const ids = cs.reduce(
(prev, { itemIds }) => [...prev, ...itemIds],
[] as string[]
)
let idsInScope: string[] = []
if (randomize) {
idsInScope = [ids[Math.floor(Math.random() * ids.length)]]
} else {
const idsPerPage = limit === -1 ? null : perPage || limit
const idsStart = idsPerPage && page ? (page - 1) * idsPerPage : 0
const idsEnd = idsPerPage && page ? page * idsPerPage : undefined
idsInScope = ids.slice(idsStart, idsEnd)
}
return {
result: await DbItemModel.find({
_id: { $in: idsInScope },
})
.select(select.join(' '))
.then((rs) => {
const rMap = rs.reduce(
(prev, c) => ({ ...prev, [c._id]: c }),
{} as Record<string, any>
)
return idsInScope.map((id) => rMap[id])
}),
count: page ? ids.length : undefined,
}
})
}
return {
result: [],
count: page ? 0 : undefined,
}
})
}
I have written this with Aggregate framework, with $lookup
and $facet
before, but it crashed, and it seemed hard to debug...
What about ORM's? Is it better to do web-server-side or database-side? What about network latency, or is it time to put database and web-server on the same machine?
Top comments (0)