#node.js #mongodb #mongoose #aggregation-framework #mongodb-aggregation
#node.js #mongodb #мангуст #агрегация-фреймворк #mongodb-агрегация
Вопрос:
Я использую mongoose 4.6.3.
У меня есть следующая схема :
var mongoose = require('mongoose');
var User = require('./User');
var TicketSchema = new mongoose.Schema({
user : { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
},
{
timestamps: true
});
var DrawSchema = new mongoose.Schema({
...
max_ticket_per_user : { type : Number, required: true },
tickets: [TicketSchema]
});
module.exports = mongoose.model('Draw', DrawSchema);
Как я могу подсчитать встроенные документы определенного пользовательского объекта (поле пользователя в TicketSchema) в билетах розыгрыша (поле tickets в DrawSchema)?
Я хочу подсчитать билеты пользователя за один розыгрыш.
Было бы лучше изменить дизайн моей схемы?
Спасибо
Ответ №1:
Вы можете использовать структуру агрегации, используя операторы $filter
and $size
, чтобы получить отфильтрованный массив с элементами, соответствующими идентификатору пользователя и его размеру соответственно, что впоследствии даст вам количество.
Для одиночной выборки рассмотрите возможность добавления $match
оператора конвейера в качестве начального шага с запросом _id для фильтрации документов в коллекции.
Для получения желаемого результата рассмотрите возможность запуска следующего конвейера агрегирования:
Draw.aggregate([
{ "$match": { "_id": drawId } },
{
"$project": {
"ticketsCount": {
"$size": {
"$filter": {
"input": "$tickets",
"as": "item",
"cond": { "$eq": [ "$$item.user", userId ] }
}
}
}
}
}
]).exec(function(err, result) {
console.log(result);
});
Комментарии:
1. Отличный ответ. Я получаю нужную мне информацию, но я хочу агрегировать только по ничьей с заданным идентификатором.
2. в ответ я получаю все идентификаторы розыгрышей с их количеством для идентификатора пользователя. Я хочу объединить только один идентификатор рисования
3. @AlexB Вам понадобится конвейерный запрос $ match для фильтрации ваших документов, как я показал в обновлении выше.
4. FWIW, большинство облачных платформ Mongodb, таких как все облачные решения, предоставляемые Heroku, пока не поддерживают версию mongo
3.4
, и, следовательно$filter
, команда не будет работать
Ответ №2:
Вы можете передавать .count()
глубокие параметры, как и любой другой объект запроса:
Draw.count({'tickets.user._id' : userId}, console.log);
Убедитесь, что переменная userId является ObjectId . Если это строка, сделайте это:
const ObjectId = require('mongoose').Types.ObjectId;
let userId = new ObjectId(incomingStringId);
Комментарии:
1. Это не сработало бы для определенного розыгрыша. Я попробую добавить «_id»: drawId