Лучший метод подсчета документов с идентификаторами объектов с использованием Mongoose?

В настоящее время я запрашиваю MongoDB с помощью Mongoose для поиска определенной категории с определенным ObjectID (например, 5ca510c87cf5db0017a59d5d), а затем подсчитываю документы в процессе с этой конкретной категорией. Однако мне интересно, есть ли лучший способ сделать это, который может вместо этого запрашивать поле name (например, «Основной») категории, таким образом, он может работать в любой другой базе данных без изменения кода для определенного идентификатора.

Это приложение Node.js, в котором Express используется для MVC, а Mongoose — для ODM.

Я упоминал функцию populate Mongoose в документации, но не могу найти хорошую аналогию.

Модель категории:

var CategorySchema = new Schema({
    name: {type: String, required: true, min: 3, max: 100}
});

Модель процесса:

var ProcessSchema = new Schema(
  {
    name: {type: String, required: true},
    machine: {type: Schema.Types.ObjectId, ref: 'Machine', required: true},
    summary: {type: String, required: true},
    serial_number: {type: String, required: true},
    category: [{type: Schema.Types.ObjectId, ref: 'Category'}]
  }
);

Контроллер процесса:

exports.index = function(req, res) {

    async.parallel({
        ...
        process_category_primary_count: function(callback) {
            Process.countDocuments({category: '5ca510c87cf5db0017a59d5d'},callback);
        },
        process_category_intermediate_count: function(callback) {
            Process.countDocuments({category: '5ca510f57cf5db0017a59d5e'},callback);
        },
        process_category_finishing_count: function(callback) {
            Process.countDocuments({category: '5ca511017cf5db0017a59d5f'},callback);
        },
        ...
    }, function(err, results) {
        res.render('index', { title: 'Dashboard Home',
                              error: err,
                              data: results });
    });
};

По умолчанию запрос find all для процесса даст такой результат:

{ category: [ 5c9d48508ee1353a2786c7d0 ],
    _id: 5ca3ca9a9743b52602d88c57,
    name: 'Milling-Detailing',
    machine: 5c9e407c6e0b26209b55dbbd,
    summary: 'Detailing pass for each object.',
    serial_number: '1002',
    __v: 0 }

Итак, по сути: я хотел бы использовать «имя» категории, а не «идентификатор» для поиска и подсчета коллекции процессов.


person sbhaseen    schedule 11.04.2019    source источник


Ответы (1)


Я думаю, вам придется использовать $lookup, чтобы иметь возможность сделать это, так что это будет изрядно больше кода.
Согласно документам MongoDB, .countDocuments() также выполняет агрегацию и добавляет { $group: { _id: null, count: { $sum: 1 } } } в качестве последнего этапа конвейера после он соответствует запросу, который вы передаете. Это просто репликация того же процесса.
Он вернет курсор с одним элементом [{ _id: null, count: <someCount> }] (-:
$unwind должен превратить поле category из массива в одну запись.

Process.aggregate([
  {
    $lookup: {
      from: 'categories',
      localField: 'category',
      foreignField: '_id',
      as: 'category'
    }
  },
  { $unwind: '$category' },
  { $match: { 'category.name': 'categoryName' } },
  { $group: { _id: null, count: { $sum: 1 } } }
], callback)
person thomasin    schedule 12.04.2019
comment
Да, это работает! Добавлено в ответ. Очень мощный, этот агрегат и поиск. Результат имеет вид [ { _id: null, count: 3 } ]. Будет ли лучший способ получить точное число («3»), а не нарезать результат (например, результат[0].count)? - person sbhaseen; 12.04.2019
comment
Для этого вам придется использовать вспомогательную функцию. aggregate возвращает курсор, который всегда будет в виде массива. - person thomasin; 13.04.2019
comment
Хорошо, я попробовал это. Думаю, теперь у меня есть рабочая цепь. Большое спасибо! - person sbhaseen; 14.04.2019