#javascript #mongodb #mongoose
#javascript #mongodb #mongoose
Вопрос:
В настоящее время я запрашиваю MongoDB с помощью Mongoose для поиска определенной категории с определенным идентификатором объекта (например, 5ca510c87cf5db0017a59d5d), а затем подсчитываю документы в процессе с этой конкретной категорией. Однако мне интересно, есть ли лучший способ сделать это, который может запрашивать name
поле (например, ‘Primary’) категории вместо этого, таким образом, он может работать в любой другой базе данных без изменения кода на определенный идентификатор.
Это 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
весь запрос для процесса выдаст результат, подобный этому:
{ category: [ 5c9d48508ee1353a2786c7d0 ],
_id: 5ca3ca9a9743b52602d88c57,
name: 'Milling-Detailing',
machine: 5c9e407c6e0b26209b55dbbd,
summary: 'Detailing pass for each object.',
serial_number: '1002',
__v: 0 }
Итак, по сути: я хотел бы использовать «имя» категории, а не «идентификатор» для поиска и подсчета коллекции процессов.
Ответ №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)
Комментарии:
1. Да, это работает! Добавлено в соответствии с ответом. Очень мощный, этот агрегат и поиск. Результат имеет вид [ { _id: null, count: 3 } ] . Есть ли лучший способ получить точное число (‘3’), а не нарезать результат (например, result [0].count)?
2. Для этого вам придется использовать вспомогательную функцию.
aggregate
возвращает курсор, который всегда будет иметь форму массива.3. Хорошо, я попробовал это. Думаю, теперь у меня есть рабочая цепочка. Большое спасибо!