Mongoose - 如何按属性值查询子文档

时间:2015-06-09 19:18:11

标签: node.js mongodb express mongoose

我试图获得一系列未付的订单。订单子文档有一个属性isPaid,用于定义订单是否已付款。

在我看来,我只想显示尚未支付的订单。

这是我的架构:

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 个答案:

答案 0 :(得分:2)

您可以采用的一种方法是使用 aggregation framework 来获取所需的数组。请考虑以下管道,该管道首先使用 $match 运算符来过滤将进入下一阶段的文档 $unwind 。此步骤从输入文档中解构orders数组字段,以输出每个元素的文档。每个输出文档都是输入文档,数组字段的值由元素替换。

下一步使用 $match 运算符,然后对解构的子文档进行进一步过滤,然后对其进行分组(使用 $group )通过标识符_id表达式,并将累加器表达式$push(在orders子文档上)应用于返回所需数组的每个组。

最后,管道看起来像这样:

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 :(得分:0)

.populate()允许您指定匹配查询。 another SO answer中的示例:

Users.find().populate({
  path: 'email',
  match: {
    type: 'Gmail'
  }
}).exec(function(err, users) {
  users = users.filter(function(user) {
    return user.email; // return only users with email matching 'type: "Gmail"' query
  });
});```