Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sorting with equality does not ensure order in pagination #14718

Closed
2 tasks done
arenier opened this issue Jul 2, 2024 · 3 comments
Closed
2 tasks done

Sorting with equality does not ensure order in pagination #14718

arenier opened this issue Jul 2, 2024 · 3 comments
Assignees
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

Comments

@arenier
Copy link

arenier commented Jul 2, 2024

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

8.3.2

Node.js version

18.20.2

MongoDB server version

6.X

Typescript version (if applicable)

No response

Description

My CourseModel contains fields as title and code and other fields.

I have 3 courses with the same title "Communication" among tens of courses but different code "COM10", "COM11", "COM12".

I want to paginate the complete list by 10 and these 3 courses are between the 9th and 11th position. One is missing and one is in double between the two pages.

I remember I had the same issue with testing data I had to avoid same creation date to keep my unit tests clean. We updated mongoose from 7.5.0 to 8.0.0 in last november.

Steps to Reproduce

const courses = await CourseModel.find().sort('title').limit(10).skip(0);
console.log(courses.map(({ title, code }) => `${title} ${code}`));

/* [
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  'Communication COM10'
] */

const courses = await CourseModel.find().sort('title').limit(10).skip(10);
console.log(courses.map(({ title, code }) => `${title} ${code}`));

/*
[
  'Communication COM10',
  'Communication COM12',
  'Communication 2 COM20',
  ....
]
*/

Expected Behavior

const courses = await CourseModel.find().sort('title').limit(10).skip(0);
console.log(courses.map(({ title, code }) => `${title} ${code}`));

/* [
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  ... 
  'Communication COM10'
] */

const courses = await CourseModel.find().sort('title').limit(10).skip(10);
console.log(courses.map(({ title, code }) => `${title} ${code}`));

/*
[
  'Communication COM11',
  'Communication COM12',
  'Communication 2 COM20',
  'XXXX',
  'XXXY',
   ....
]
*/
@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Jul 2, 2024
@IslandRhythms
Copy link
Collaborator

This may not necessarily be a bug. Its sorting documents with the same title and so order doesn't matter in that case which may cause the behavior being described.

const mongoose = require('mongoose');

const courseSchema = new mongoose.Schema({
    title: String,
    code: String
});


const Course = mongoose.model('Course', courseSchema);

async function run() {
    await mongoose.connect('mongodb://localhost:27017');
    await mongoose.connection.dropDatabase();

    for (let i = 0; i < 21; i++) {
        await Course.create({
            title: 'COM',
            code: `${i}`
        });
    }

    let courses = await Course.find().sort('title').limit(10).skip(0);
    console.log(courses.map(({ title, code }) => `${title} ${code}`));

    courses = await Course.find().sort('title').limit(10).skip(10);
    console.log(courses.map(({ title, code }) => `${title} ${code}`));

}

run();

@vkarpov15 vkarpov15 added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary and removed confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. labels Jul 2, 2024
@vkarpov15
Copy link
Collaborator

This is expected behavior on the MongoDB server. await CourseModel.find().sort('title') doesn't guarantee order beyond the title prop, so if you have multiple docs with the same title MongoDB may order them in any way in the result set.

There's a couple workarounds:

  1. Sort by title and code: await CourseModel.find().sort({ title: 1, code: 1 }).limit(10).skip(10)
  2. Sort by title and _id: await CourseModel.find().sort({ title: 1, _id: 1 }).limit(10).skip(10)

@arenier
Copy link
Author

arenier commented Jul 11, 2024

I was pretty sure, that was a MongoDB behavior.

That's strange to witness this behavior, I'll do the workaround. Thanks for help.

vkarpov15 added a commit that referenced this issue Jul 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
Projects
None yet
Development

No branches or pull requests

3 participants