Loading...
Loading...
In some cases, clustered collections incorrectly return results that should be filtered out by the $lt operator. Specifically, this query: db.clustered_repro.find({ _id: { $lt: 3 } }).sort({ _id: -1 }) May return a document with { _id: 3 }. The same happens when using an aggregation pipeline. Removing the sort condition, using ascending sort, or changing to $lte, resolves the issue. But I could find no workaround without changing the query or using a plain collection.
xgen-internal-githook commented on Fri, 10 Apr 2026 15:46:36 +0000: Author: {'name': 'Naafiyan Ahmed', 'email': 'naafiyan.ahmed@mongodb.com', 'username': 'naafiyan'} Message: SERVER-121822: Add scan direction check for clustered scan bounds (#51324) GitOrigin-RevId: e0308f70ede9296826d41e23cd49297b6e8217b9 Branch: master https://github.com/mongodb/mongo/commit/ebeb649a5c5795b343ba625096757ea787a4de27 xgen-internal-githook commented on Mon, 6 Apr 2026 18:22:12 +0000: Author: {'name': 'Ian Boros', 'email': '87138302+borosaurus@users.noreply.github.com', 'username': 'borosaurus'} Message: Revert "SERVER-121822: Add scan direction check for clustered scan bo… (#51201) GitOrigin-RevId: a1f62ede8df6933565a37283bd52018dd6b583c1 Branch: master https://github.com/mongodb/mongo/commit/1ec83b0e265f5b4fd244d24da516570e1be78d8f JIRAUSER1282024 commented on Mon, 6 Apr 2026 18:13:42 +0000: Ticket re-opened due to revert. xgen-internal-githook commented on Thu, 26 Mar 2026 17:33:57 +0000: Author: {'name': 'Naafiyan Ahmed', 'email': 'naafiyan.ahmed@mongodb.com', 'username': 'naafiyan'} Message: SERVER-121822: Add scan direction check for clustered scan bounds (#50350) GitOrigin-RevId: b100dbf993646a3ec3cc60cfec2eb445d5b92259 Branch: master https://github.com/mongodb/mongo/commit/3d995dbfee7b60955ccb405f8f9f63645a1d9c18
NodeJS script reproducing the issue: import * as mongo from 'mongodb'; /** * Run with: * export MONGO_TEST_URL='mongodb://localhost:27017/clustered_test' * node script.mjs */ const MONGO_URL = process.env.MONGO_TEST_URL ?? 'mongodb://localhost:27017/clustered_test'; const client = new mongo.MongoClient(MONGO_URL); const db = client.db(); const clusteredName = `clustered_repro`; const plainName = `plain_repro`; await client.connect(); // Ensure the client is closed when the script finishes await using _ = { [Symbol.asyncDispose]: async () => await client.close() }; const buildInfo = await db.command({ buildInfo: 1 }); console.log(`MongoDB version: ${buildInfo.version}`); console.log(`Database: ${MONGO_URL}`); // Make sure the collections don't exist before running the test await db .collection(clusteredName) .drop() .catch(() => {}); await db .collection(plainName) .drop() .catch(() => {}); await db.createCollection(clusteredName, { clusteredIndex: { name: '_id', unique: true, key: { _id: 1 } } }); await db.createCollection(plainName); const clustered = db.collection(clusteredName); const plain = db.collection(plainName); const docs = [{ _id: 1 }, { _id: 2 }, { _id: 3 }, { _id: 4 }]; await clustered.insertMany(docs); await plain.insertMany(docs); const plainResults1 = await plain .find( { _id: { $lt: 3 } }, { sort: { _id: -1 } } ) .toArray(); const plainResults2 = await plain .aggregate([ { $match: { _id: { $lt: 3 } } }, { $sort: { _id: -1 } } ]) .toArray(); // This one fails - includes { _id: 3 } const clusteredResults1 = await clustered .find( { _id: { $lt: 3 } }, { sort: { _id: -1 } } ) .toArray(); // This one also fails - includes { _id: 3 } const clusteredResults2 = await clustered .aggregate([ { $match: { _id: { $lt: 3 } } }, { $sort: { _id: -1 } } ]) .toArray(); const clusteredResults3 = await clustered .aggregate([ { $match: { _id: { $lt: 3 } } }, { $sort: { _id: 1 } } ]) .toArray(); const clusteredResults4 = await clustered .find( { _id: { $lte: 2 } }, { sort: { _id: -1 } } ) .toArray(); const clusteredResults5 = await clustered .aggregate([ { $match: { _id: { $lte: 2 } } }, { $sort: { _id: -1 } } ]) .toArray(); console.log('These should all filter out { _id: 3 }'); console.log('Plain 1:', plainResults1, '# find'); console.log('Plain 2:', plainResults2, '# aggregate'); console.log('Clustered 1:', clusteredResults1, '# find'); console.log('Clustered 2:', clusteredResults2, '# aggregate, sort _id: -1'); console.log('Clustered 3:', clusteredResults3, '# aggregate, sort _id: 1'); console.log('Clustered 4:', clusteredResults4, '# find, sort _id: -1, $lte 2'); console.log('Clustered 5:', clusteredResults5, '# aggregate, sort _id: -1, $lte 2'); Tested on 8.0.19 and 8.2.6-rc0. Results: MongoDB version: 8.2.6-rc0 Database: mongodb://localhost:27017/clustered_test These should all filter out { _id: 3 } Plain 1: [ { _id: 2 }, { _id: 1 } ] # find Plain 2: [ { _id: 2 }, { _id: 1 } ] # aggregate Clustered 1: [ { _id: 3 }, { _id: 2 }, { _id: 1 } ] # find Clustered 2: [ { _id: 3 }, { _id: 2 }, { _id: 1 } ] # aggregate, sort _id: -1 Clustered 3: [ { _id: 1 }, { _id: 2 } ] # aggregate, sort _id: 1 Clustered 4: [ { _id: 2 }, { _id: 1 } ] # find, sort _id: -1, $lte 2 Clustered 5: [ { _id: 2 }, { _id: 1 } ] # aggregate, sort _id: -1, $lte 2
MongoDB Integration
Learn more about where this data comes from
Bug Scrub Advisor
Streamline upgrades with automated vendor bug scrubs
BugZero Enterprise
Wish you caught this bug sooner? Get proactive today.