Querying by composite _id

I am using models with a customised composite _id, whose form is illustrated in the schema example below:

import { Types } from 'mongoose';

const exampleSchema = new mongoose.Schema({
   _id : {
      field1: String,
      field2: Types.ObjectId
   },
  ... other fields
})
// this schema is then used to create the model exampleModel

Since we tend to query this type of document using field1 and field2, it made sense to define the _id as an object consisting of {field1, field2}, and thus have just a single index on this composite _id.
However, when I try to search for a document that exists in my database via findById({field1, field2}), the document is not found.
It is found in MongoDB Compass when I type {_id: {field1: ‘valueOfField1’, field2: ‘valueOfField2’} } into the query box, but in my Node.js app that talks to the same database, exampleModel.findById({field1: ‘valueOfField1’, field2: ‘valueOfField2’}) does not turn up anything.

I also tried querying with exampleModel.exists( {_id: {field1: ‘valueOfField1’, field2: ‘valueOfField2’} }), and that failed to find anything as well.
What am I doing incorrectly?

Try

exampleModel.exists( { '_id.field1' : 'valueOfField1' , '_id.field2' : 'valueOfField2' })

One pitfall about object equality is that in certain cases, objects are considered equals if and only if the fields are in the same order. For example, in mongosh (nodejs based):

Atlas rent-shard-0 [primary] test> _id_1 = { a : 1 , b : 2 }
{ a: 1, b: 2 }
Atlas rent-shard-0 [primary] test> _id_2 = { b : 2 , a : 1 }
{ b: 2, a: 1 }
// Object equality is false
Atlas rent-shard-0 [primary] test> _id_1 === _id_2
false
// But field by field equality is true 
Atlas rent-shard-0 [primary] test> _id_1.a === _id_2.a && _id_1.b == _id_2.b
true
Atlas rent-shard-0 [primary] test> c.find()
[ { _id: { a: 1, b: 2 } }, { _id: { b: 2, a: 1 } } ]
// Same is true for the server, object equality only return document with same value and order
Atlas rent-shard-0 [primary] test> c.find( { _id : _id_1 } )
[ { _id: { a: 1, b: 2 } } ]
// But we dot notation we have field by field comparison
Atlas rent-shard-0 [primary] test> c.find( { '_id.a' : 1 , '_id.b' : 2 } )
[ { _id: { a: 1, b: 2 } }, { _id: { b: 2, a: 1 } } ]


1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.