Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/db-mongodb/src/count.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ export const count: Count = async function count(
session: await getSession(this, req),
}

if (this.collation) {
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

options.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
}
}

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,
Expand Down
11 changes: 11 additions & 0 deletions packages/db-mongodb/src/countGlobalVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ export const countGlobalVersions: CountGlobalVersions = async function countGlob
session: await getSession(this, req),
}

if (this.collation) {
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

options.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
}
}

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,
Expand Down
11 changes: 11 additions & 0 deletions packages/db-mongodb/src/countVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ export const countVersions: CountVersions = async function countVersions(
session: await getSession(this, req),
}

if (this.collation) {
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

options.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
}
}

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,
Expand Down
19 changes: 18 additions & 1 deletion packages/db-mongodb/src/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ export const find: Find = async function find(
}

if (this.collation) {
const defaultLocale = 'en'
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

paginationOptions.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
Expand All @@ -105,11 +108,25 @@ export const find: Find = async function find(
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
hint: { _id: 1 },
session,
}),
)
}
} else if (!useEstimatedCount && this.collation) {
// Workaround for mongoose-paginate-v2 bug: chaining .collation() on countDocuments breaks
// session context in transactions (mongoose 8.x). Provide custom count function that passes
// collation as an option instead. See: https://github.com/aravindnc/mongoose-paginate-v2/pull/240
// TODO: Remove this workaround once mongoose-paginate-v2 is updated with the fix.
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
session,
}),
)
}
}

if (limit >= 0) {
Expand Down
19 changes: 18 additions & 1 deletion packages/db-mongodb/src/findGlobalVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
}

if (this.collation) {
const defaultLocale = 'en'
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

paginationOptions.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
Expand All @@ -95,11 +98,25 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
hint: { _id: 1 },
session,
}),
)
}
} else if (!useEstimatedCount && this.collation) {
// Workaround for mongoose-paginate-v2 bug: chaining .collation() on countDocuments breaks
// session context in transactions (mongoose 8.x). Provide custom count function that passes
// collation as an option instead. See: https://github.com/aravindnc/mongoose-paginate-v2/pull/240
// TODO: Remove this workaround once mongoose-paginate-v2 is updated with the fix.
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
session,
}),
)
}
}

if (limit >= 0) {
Expand Down
19 changes: 18 additions & 1 deletion packages/db-mongodb/src/findVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ export const findVersions: FindVersions = async function findVersions(
}

if (this.collation) {
const defaultLocale = 'en'
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

paginationOptions.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
Expand All @@ -103,11 +106,25 @@ export const findVersions: FindVersions = async function findVersions(
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
hint: { _id: 1 },
session,
}),
)
}
} else if (!useEstimatedCount && this.collation) {
// Workaround for mongoose-paginate-v2 bug: chaining .collation() on countDocuments breaks
// session context in transactions (mongoose 8.x). Provide custom count function that passes
// collation as an option instead. See: https://github.com/aravindnc/mongoose-paginate-v2/pull/240
// TODO: Remove this workaround once mongoose-paginate-v2 is updated with the fix.
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(query, {
collation: paginationOptions.collation,
session,
}),
)
}
}

if (limit >= 0) {
Expand Down
20 changes: 19 additions & 1 deletion packages/db-mongodb/src/queryDrafts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
}

if (this.collation) {
const defaultLocale = 'en'
const localizationConfig = this.payload.config.localization
const defaultLocale =
(typeof localizationConfig === 'object' && localizationConfig?.defaultLocale) || 'en'

paginationOptions.collation = {
locale: locale && locale !== 'all' && locale !== '*' ? locale : defaultLocale,
...this.collation,
Expand All @@ -114,7 +117,22 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(versionQuery, {
collation: paginationOptions.collation,
hint: { _id: 1 },
session,
}),
)
}
} else if (!useEstimatedCount && this.collation) {
// Workaround for mongoose-paginate-v2 bug: chaining .collation() on countDocuments breaks
// session context in transactions (mongoose 8.x). Provide custom count function that passes
// collation as an option instead. See: https://github.com/aravindnc/mongoose-paginate-v2/pull/240
// TODO: Remove this workaround once mongoose-paginate-v2 is updated with the fix.
paginationOptions.useCustomCountFn = () => {
return Promise.resolve(
Model.countDocuments(versionQuery, {
collation: paginationOptions.collation,
session,
}),
)
}
Expand Down
52 changes: 52 additions & 0 deletions test/database/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5617,4 +5617,56 @@ describe('database', () => {
expect(collatedMappedResults).toEqual(expectedSortedItems)
},
)

it(
'ensure mongodb collation works with draft pagination without sort',
{ db: 'mongo' },
async () => {
// Clear any existing documents
await payload.delete({ collection: 'categories', where: {} })

// Create 15 draft documents
const createdIds: (number | string)[] = []
for (let i = 0; i < 15; i++) {
const doc = await payload.create({
collection: 'categories',
data: { name: `Category ${i}` },
draft: true,
})
createdIds.push(doc.id)
}

// Enable collation
payload.db.collation = { strength: 2 }

// Query drafts WITHOUT sort - this is the scenario that breaks
const resultsNoSort = await payload.find({
collection: 'categories',
limit: 10,
draft: true,
// No sort parameter
})

console.log({
totalDocs: resultsNoSort.totalDocs,
totalPages: resultsNoSort.totalPages,
docsLength: resultsNoSort.docs.length,
hasNextPage: resultsNoSort.hasNextPage,
})

// The bug: totalDocs returns 10 (same as limit) instead of 15
expect(resultsNoSort.totalDocs).toBe(15)
expect(resultsNoSort.totalPages).toBe(2)
expect(resultsNoSort.hasNextPage).toBe(true)
expect(resultsNoSort.docs.length).toBe(10)

// Clean up
for (const id of createdIds) {
await payload.delete({ collection: 'categories', id })
}

// Reset collation
payload.db.collation = undefined
},
)
})
Loading