Skip to content

Commit 2647b61

Browse files
JoCatnbbeeken
andauthored
fix(NODE-5126): find operations fail when passed an ObjectId as filter (#3604)
Co-authored-by: Neal Beeken <neal.beeken@mongodb.com>
1 parent 6537e27 commit 2647b61

File tree

4 files changed

+129
-2
lines changed

4 files changed

+129
-2
lines changed

src/operations/find.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class FindOperation extends CommandOperation<Document> {
104104
}
105105

106106
// special case passing in an ObjectId as a filter
107-
this.filter = filter != null && filter._bsontype === 'ObjectID' ? { _id: filter } : filter;
107+
this.filter = filter != null && filter._bsontype === 'ObjectId' ? { _id: filter } : filter;
108108
}
109109

110110
override execute(

test/integration/crud/find.test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,4 +2577,44 @@ describe('Find', function () {
25772577
});
25782578
}
25792579
});
2580+
2581+
context('when passed an ObjectId instance as the filter', () => {
2582+
let client;
2583+
let findsStarted;
2584+
2585+
beforeEach(function () {
2586+
client = this.configuration.newClient({ monitorCommands: true });
2587+
findsStarted = [];
2588+
client.on('commandStarted', ev => {
2589+
if (ev.commandName === 'find') findsStarted.push(ev.command);
2590+
});
2591+
});
2592+
2593+
afterEach(async function () {
2594+
findsStarted = undefined;
2595+
await client.close();
2596+
});
2597+
2598+
context('find(oid)', () => {
2599+
it('wraps the objectId in a document with _id as the only key', async () => {
2600+
const collection = client.db('test').collection('test');
2601+
const oid = new ObjectId();
2602+
await collection.find(oid).toArray();
2603+
expect(findsStarted).to.have.lengthOf(1);
2604+
expect(findsStarted[0]).to.have.nested.property('filter._id', oid);
2605+
expect(findsStarted[0].filter).to.have.all.keys('_id');
2606+
});
2607+
});
2608+
2609+
context('findOne(oid)', () => {
2610+
it('wraps the objectId in a document with _id as the only key', async () => {
2611+
const collection = client.db('test').collection('test');
2612+
const oid = new ObjectId();
2613+
await collection.findOne(oid);
2614+
expect(findsStarted).to.have.lengthOf(1);
2615+
expect(findsStarted[0]).to.have.nested.property('filter._id', oid);
2616+
expect(findsStarted[0].filter).to.have.all.keys('_id');
2617+
});
2618+
});
2619+
});
25802620
});

test/integration/crud/find_and_modify.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const { format: f } = require('util');
44
const { setupDatabase, assert: test } = require(`../shared`);
55
const { expect } = require('chai');
66

7+
const { ObjectId, MongoServerError } = require('../../mongodb');
8+
79
describe('Find and Modify', function () {
810
before(function () {
911
return setupDatabase(this.configuration);
@@ -318,4 +320,57 @@ describe('Find and Modify', function () {
318320
expect(error.message).to.match(/must not contain atomic operators/);
319321
await client.close();
320322
});
323+
324+
context('when passed an ObjectId instance as the filter', () => {
325+
let client;
326+
let findAndModifyStarted;
327+
328+
beforeEach(function () {
329+
client = this.configuration.newClient({ monitorCommands: true });
330+
findAndModifyStarted = [];
331+
client.on('commandStarted', ev => {
332+
if (ev.commandName === 'findAndModify') findAndModifyStarted.push(ev.command);
333+
});
334+
});
335+
336+
afterEach(async function () {
337+
findAndModifyStarted = undefined;
338+
await client.close();
339+
});
340+
341+
context('findOneAndDelete(oid)', () => {
342+
it('sets the query to be the ObjectId instance', async () => {
343+
const collection = client.db('test').collection('test');
344+
const oid = new ObjectId();
345+
const error = await collection.findOneAndDelete(oid).catch(error => error);
346+
expect(error).to.be.instanceOf(MongoServerError);
347+
expect(findAndModifyStarted).to.have.lengthOf(1);
348+
expect(findAndModifyStarted[0]).to.have.property('query', oid);
349+
});
350+
});
351+
352+
context('findOneAndReplace(oid)', () => {
353+
it('sets the query to be the ObjectId instance', async () => {
354+
const collection = client.db('test').collection('test');
355+
const oid = new ObjectId();
356+
const error = await collection.findOneAndReplace(oid, {}).catch(error => error);
357+
expect(error).to.be.instanceOf(MongoServerError);
358+
expect(findAndModifyStarted).to.have.lengthOf(1);
359+
expect(findAndModifyStarted[0]).to.have.property('query', oid);
360+
});
361+
});
362+
363+
context('findOneAndUpdate(oid)', () => {
364+
it('sets the query to be the ObjectId instance', async () => {
365+
const collection = client.db('test').collection('test');
366+
const oid = new ObjectId();
367+
const error = await collection
368+
.findOneAndUpdate(oid, { $set: { a: 1 } })
369+
.catch(error => error);
370+
expect(error).to.be.instanceOf(MongoServerError);
371+
expect(findAndModifyStarted).to.have.lengthOf(1);
372+
expect(findAndModifyStarted[0]).to.have.property('query', oid);
373+
});
374+
});
375+
});
321376
});

test/integration/gridfs/gridfs.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { expect } from 'chai';
22
import { once } from 'events';
33

4-
import { CommandStartedEvent, type Db, GridFSBucket, type MongoClient } from '../../mongodb';
4+
import {
5+
CommandStartedEvent,
6+
type Db,
7+
GridFSBucket,
8+
type MongoClient,
9+
ObjectId
10+
} from '../../mongodb';
511
import { sleep } from '../../tools/utils';
612

713
describe('GridFS', () => {
@@ -115,5 +121,31 @@ describe('GridFS', () => {
115121
const createIndexes = commandStartedEvents.filter(e => e.commandName === 'createIndexes');
116122
expect(createIndexes).to.have.lengthOf(0);
117123
});
124+
125+
context('find(oid)', () => {
126+
let findsStarted;
127+
128+
beforeEach(function () {
129+
findsStarted = [];
130+
client.on('commandStarted', ev => {
131+
if (ev.commandName === 'find') findsStarted.push(ev.command);
132+
});
133+
});
134+
135+
afterEach(async function () {
136+
findsStarted = undefined;
137+
await client.close();
138+
});
139+
140+
context('when passed an ObjectId instance as the filter', () => {
141+
it('wraps the objectId in a document with _id as the only key', async () => {
142+
const oid = new ObjectId();
143+
await bucket.find(oid).toArray();
144+
expect(findsStarted).to.have.lengthOf(1);
145+
expect(findsStarted[0]).to.have.nested.property('filter._id', oid);
146+
expect(findsStarted[0].filter).to.have.all.keys('_id');
147+
});
148+
});
149+
});
118150
});
119151
});

0 commit comments

Comments
 (0)