mongodb / mongoose findMany - знайдіть усі документи з ідентифікаторами, переліченими в масиві


246

У мене є масив _ids, і я хочу отримати всі документи відповідно, який найкращий спосіб це зробити?

Щось на зразок ...

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

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

Масив може містити сотні _ids.

Відповіді:


479

findФункція мангуста є повним запитом до MongoDB. Це означає, що ви можете використовувати зручний $inпункт mongoDB , який працює так само, як і версія SQL тієї ж.

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

Цей метод буде добре працювати навіть для масивів, що містять десятки тисяч ідентифікаторів. (Див. Ефективне визначення власника запису )

Я рекомендую mongoDBвсім , хто працює з цим, прочитати розділ « Розширені запити» відмінних офіційних документів MongoDB


9
Вигляд із запізненням на цю дискусію, але як би ви гарантували, що порядок повернених елементів відповідає порядку масиву елементів, які ви надаєте в масиві? Не гарантується, що документи вийдуть в будь-якому порядку, якщо ви не вкажете сортування. Що робити, якщо ви хочете, щоб вони були відсортовані в одному порядку, ви перераховуєте їх у масиві (наприклад, ... 000c, ... 000d, ... 000e)?
Кевін

7
Це не вдалося чомусь. У мене з’явився порожній масив документів
chovy

2
@chovy спробуйте перетворити їх спочатку в ObjectIds , а не передавати рядки.
Георгій Христозов

@GeorgiHristozov Я використовую користувальницький генератор ідентифікаторів ... чи перетворення на ObjectId все ще працює? (мангуст + короткий)
човен

1
@Schybo це абсолютно не має значення. { _id : 5 }те саме, що { '_id' : 5 }.
royhowie

27

Ідс - це масив об’єктних ідентифікаторів:

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

Використання Mongoose із зворотним зв'язком:

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

Використання мангуста з функцією асинхронізації:

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

Не забудьте змінити модель на свою фактичну модель.


Це має бути прийнятою відповіддю, оскільки вона є найсучаснішою та узгодженою. Вам не доведеться конвертувати ідентифікатори в ObjectId, як у прийнятій відповіді, і він використовує запити мангустичного імперативного стилю. Спасибі, btw!
Хаві Марзан

Це дуже чистий і оновлений метод, якщо ви не заперечуєте, я хотів би задати кілька питань, якщо у мене є масив посилань ObjectId, як описано вище (скажімо, у мене є проекти, і я призначив масив проектів для певних користувачів із посиланням project_id на користувацькій моделі), якщо я видаляю проект, як я переконуюсь, що idвидалено з масиву, на який посилається модель користувача? Дякую килимок
Легкий

9

Використовуйте цей формат запитів

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();

4

І node.js, і MongoChef змушують мене переходити до ObjectId. Це те, що я використовую, щоб схопити список користувачів із БД та отримати декілька властивостей. Майте на увазі перетворення типів у рядку 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 );
                }
            }
        });
    }

7
userIds = _.map (список, функція (userId) {return mongoose.Types.ObjectId (userId)};
Майкл Драпер

1
Мені не довелося конвертувати в ObjectID, використовуючи мангусту 4.5.9.
Флоріан Вендельборн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.