2015-06-09 3 views
3

Я пытаюсь получить массив неоплаченных заказов. Поддокумент заказа имеет свойство isPaid, которое определяет, был ли уплачен заказ.Mongoose - Как запросить поддокумент по значению свойства

На мой взгляд, я хочу отображать только заказы, которые не были оплачены.

Вот моя схема:

var order = new Schema({ 
    content: [{ 
     product: {type: String, required: true}, 
     quantity: {type: Number}, 
     vatRate: {type: Number, required: true}, 
     price: {type: Number} 
    }], 
    isPaid: {type: Boolean, default: false}, 
    number: {type: Number} 
}); 

var clientSchema = new Schema({ 
[...] 
information: { 
    code: {type: String, required: true}, 
    name: {type: String, required: true} 
}, 
orders: [order], 
[...] 
}); 

Я начал с, но без успеха

clientModel.find(
    { 
     "information.code": clientCode, 
     "orders.isPaid": false 
    }, function (err, client) { ... }); 

Затем я сделал много попыток, с $all, $elemMatch без успеха. В большинстве случаев он возвращает все заказы, оплачиваемые или неоплаченные. Я не знаю почему. Мне нужна помощь, пожалуйста :)

ответ

2

Один из способов, которые вы могли бы предпринять, - использовать aggregation framework для получения нужного массива. Рассмотрим следующий трубопровод, в котором сначала используется оператор для фильтрации документов, которые будут переведены на следующий этап, $unwind. Этот шаг деконструирует поле массива заказов из входных документов для вывода документа для каждого элемента. Каждый выходной документ является входным документом со значением поля массива, замененного элементом.

Следующего шаг использует оператор в $match, чтобы затем выполнить дополнительную фильтрацию на снесенные поддокументах, которые затем будут сгруппированы (с использованием $group) выражением идентификатора _id и применяет выражение аккумулятора $push (на поддокументе заказов) каждой группе, которая возвращает нужный массив.

В конце трубопровода будет выглядеть следующим образом:

var pipeline = [ 
    { 
     "$match": { 
      "information.code": clientCode, 
      "orders.isPaid": false 
     } 
    }, 
    { "$unwind": "$orders" }, 
    { 
     "$match": {  
      "orders.isPaid": false 
     } 
    }, 
    { 
     "$group": { 
      "_id": "$_id", 
      "orders": { 
       "$push": "$orders" 
      } 
     } 
    } 
] 

clientModel.aggregate(pipeline).exec(function (err, res){ 
    if (err) return handleError(err); 
    console.log(res); // [ { orders: [...] } ] 
}); 

или с помощью aggregation pipeline builder:

clientModel.aggregate() 
    .match({"information.code": clientCode, "orders.isPaid": false}) 
    .unwind("orders") 
    .match({"orders.isPaid": false }) 
    .group({"_id": "$_id", "orders": { "$push": "$orders" } }) 
    .select("-_id orders") 
    .exec(function (err, res) { 
     if (err) return handleError(err); 
     console.log(res); // [ { orders: [...] } ] 
    }); 
+1

Большое спасибо !!! Он работает как шарм и благодарит за объяснение. – Pat

Смежные вопросы