ChatGPT解决这个技术问题 Extra ChatGPT

mongodb/mongoose findMany - find all documents with IDs listed in array

I have an array of _ids and I want to get all docs accordingly, what's the best way to do it ?

Something like ...

// doesn't work ... of course ...

model.find({
    '_id' : [
        '4ed3ede8844f0f351100000c',
        '4ed3f117a844e0471100000d', 
        '4ed3f18132f50c491100000e'
    ]
}, function(err, docs){
    console.log(docs);
});

The array might contain hundreds of _ids.


C
Community

The find function in mongoose is a full query to mongoDB. This means you can use the handy mongoDB $in clause, which works just like the SQL version of the same.

model.find({
    '_id': { $in: [
        mongoose.Types.ObjectId('4ed3ede8844f0f351100000c'),
        mongoose.Types.ObjectId('4ed3f117a844e0471100000d'), 
        mongoose.Types.ObjectId('4ed3f18132f50c491100000e')
    ]}
}, function(err, docs){
     console.log(docs);
});

This method will work well even for arrays containing tens of thousands of ids. (See Efficiently determine the owner of a record)

I would recommend that anybody working with mongoDB read through the Advanced Queries section of the excellent Official mongoDB Docs


Kind of late to this discussion, but how would you ensure the order of the items returned matches the order of the array of items you provide in the array? Documents are not guaranteed to come out in any order unless you specify a sort. What if you want them sorted in the same order you list them in the array (e.g. ...000c, ...000d, ...000e)?
This did not work for some reason. I got an empty array of docs
@chovy try converting them to ObjectIds first, instead of passing strings.
@Kevin You might be interested in this answer: stackoverflow.com/a/22800784/133408
@Schybo that makes absolutely no difference. { _id : 5 } is the same as { '_id' : 5 }.
s
snnsnn

Ids is the array of object ids:

const ids =  [
    '4ed3ede8844f0f351100000c',
    '4ed3f117a844e0471100000d', 
    '4ed3f18132f50c491100000e',
];

Using Mongoose with callback:

Model.find().where('_id').in(ids).exec((err, records) => {});

Using Mongoose with async function:

const records = await Model.find().where('_id').in(ids).exec();

Or more concise:

const records = await Model.find({ '_id': { $in: ids } });

Don't forget to change Model with your actual model.


This should be the accepted answer as it is the most up to date and coherent one. You don't have to convert the ids to ObjectId as in the accepted answer, and it uses the mongoose imperative style queries. Thanks btw!
This is a very clean and updated method, if you don't mind I'd like to ask a few question, if I have an array of referenced ObjectId's like the above (say, I have projects, and I assigned an array of projects to certain users with the project_id referenced on the user model), if I delete a project, how do I make sure the id is deleted from the array referenced from the user model ? Thanks mat.
this is what I needed! It's clean and easy to use with ids that are a ref in another model
This works well ! For an optimized version, you can attach .lean() at the end which will return only POJO ( Plain Old Javascript Object ). You can also add select() and pick only the required fields of the document.
A
Ahmad Agbaryah

Combining Daniel's and snnsnn's answers:

let ids = ['id1','id2','id3'] let data = await MyModel.find( {'_id': { $in: ids}} );

Simple and clean code. It works and tested against:

"mongodb": "^3.6.0", "mongoose": "^5.10.0",


I kept putting the ids inside of array brackets [] but realized from your answer that it is already an array :|
@RizaKhan thank you so much! I made the same exact mistake.
l
long.luc

Use this format of querying

let arr = _categories.map(ele => new mongoose.Types.ObjectId(ele.id));

Item.find({ vendorId: mongoose.Types.ObjectId(_vendorId) , status:'Active'})
  .where('category')
  .in(arr)
  .exec();

f
fafa.mnzm

This code works for me just fine as of mongoDB v4.2 and mongoose 5.9.9:

const Ids = ['id1','id2','id3']
const results = await Model.find({ _id: Ids})

and the Ids can be of type ObjectId or String


works perfectly.
N
Nico

Both node.js and MongoChef force me to convert to ObjectId. This is what I use to grab a list of users from the DB and fetch a few properties. Mind the type conversion on line 8.

// this will complement the list with userName and userPhotoUrl based on userId field in each item
augmentUserInfo = function(list, callback){
        var userIds = [];
        var users = [];         // shortcut to find them faster afterwards
        for (l in list) {       // first build the search array
            var o = list[l];
            if (o.userId) {
                userIds.push( new mongoose.Types.ObjectId( o.userId ) );           // for the Mongo query
                users[o.userId] = o;                                // to find the user quickly afterwards
            }
        }
        db.collection("users").find( {_id: {$in: userIds}} ).each(function(err, user) {
            if (err) callback( err, list);
            else {
                if (user && user._id) {
                    users[user._id].userName = user.fName;
                    users[user._id].userPhotoUrl = user.userPhotoUrl;
                } else {                        // end of list
                    callback( null, list );
                }
            }
        });
    }

userIds = _.map(list, function(userId){ return mongoose.Types.ObjectId(userId) };
I didn't have to convert to ObjectID using mongoose 4.5.9.
M
MD SHAYON

if you are using the async-await syntax you can use

const allPerformanceIds = ["id1", "id2", "id3"];
const findPerformances = await Performance.find({ _id: { $in: allPerformanceIds } });
           

U
Uma Devi Hariram

I tried like below and its works for me.

var array_ids=['1','2','6','9'] // your array of ids
model.find({ '_id': { $in: array_ids }}).toArray(function(err, data) {
            if (err) {
                logger.winston.error(err);
            } else {
                console.log("data", data);
            }
        });

T
Tiny Bot

I am using this query to find the files in mongo GridFs. I wanted to get the by its Ids.

For me this solution is working: Ids type of ObjectId.

gfs.files
.find({ _id: mongoose.Types.ObjectId('618d1c8176b8df2f99f23ccb') })
.toArray((err, files) => {
  if (!files || files.length === 0) {
    return res.json('no file exist');
  }
  return res.json(files);
  next();
});

This is not working: Id type of string

gfs.files
.find({ _id: '618d1c8176b8df2f99f23ccb' })
.toArray((err, files) => {
  if (!files || files.length === 0) {
    return res.json('no file exist');
  }
  return res.json(files);
  next();
});