Files
payload/packages/db-mongodb/src/count.ts
Sasha b08ff88fbd fix(db-mongodb): mongodb optimizations (#10120)
There are few issues introduced in #9594 that we need to look into with
these changes.
2024-12-21 07:42:44 -05:00

56 lines
1.7 KiB
TypeScript

import type { CountOptions } from 'mongodb'
import type { Count } from 'payload'
import { flattenWhereToOperators } from 'payload'
import type { MongooseAdapter } from './index.js'
import { getSession } from './utilities/getSession.js'
export const count: Count = async function count(
this: MongooseAdapter,
{ collection, locale, req, where },
) {
const Model = this.collections[collection]
const options: CountOptions = {
session: await getSession(this, req),
}
let hasNearConstraint = false
if (where) {
const constraints = flattenWhereToOperators(where)
hasNearConstraint = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near'))
}
const query = await Model.buildQuery({
locale,
payload: this.payload,
where,
})
// useEstimatedCount is faster, but not accurate, as it ignores any filters. It is thus set to true if there are no filters.
const useEstimatedCount = hasNearConstraint || !query || Object.keys(query).length === 0
if (!useEstimatedCount && Object.keys(query).length === 0 && this.disableIndexHints !== true) {
// Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding
// a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents,
// which makes queries very slow. This only happens when no query (filter) is provided. If one is provided, it uses
// the correct indexed field
options.hint = {
_id: 1,
}
}
let result: number
if (useEstimatedCount) {
result = await Model.estimatedDocumentCount({ session: options.session })
} else {
result = await Model.countDocuments(query, options)
}
return {
totalDocs: result,
}
}