猫鼬过滤器按对象中的值嵌套对象的数组

发布时间:2020-07-07 18:00

我有这样的订单模式

const OrderSchema = new Schema({
  user: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
  orderDate: { type: Date, default: Date.now },
  products: { type: Array, default: [] }
});

const Order = mongoose.model("Order", OrderSchema);
module.exports = Order;

每个订单都属于一个特定的客户(用户),用户可以从不同的卖家那里购买产品

所以products数组是这样的:

"products" : [
      {
        _id: "5f0289147b9b980f40d4f2e6",
        product: ObjectId("5f02879f7160ae0c2c203cdf"),
        quantity: 1
      },
      {
        _id: "5f0289177b9b980f40d4f2e7",
        product: ObjectId("5f02879f7160ae0c2c203fgg"),
        quantity: 1
      }
    ]

数组中的每个产品都是这样的:

"product" : {
  _id: "5f02879f7160ae0c2c203cdf",
  name: "Some Car",
  category: "5f027c5ca1b94820b856c508",
  seller: "5f0276cf965f8c29e019a7f1" //seller can be different for each product
}

所以我要实现的是过滤所有订单,以获取每个卖方出售的所有产品。 就像我是卖家并登录后一样,我想在订单集合中出售我出售的所有产品

我做了一个方法,我得到所有的Orders集合,然后将产品填充到products数组中,然后根据我想要的条件过滤所有数据,它对我有用,但是它有2个foreach,所以越大数据变慢了应用程序的速度,那么有没有一种方法可以只使用猫鼬呢?还是最好的方法?

Order.find()
  .populate({ path: "products.product", model: "Product" })
  .exec((err, orders) => {
    if (err) res.status(400).json({ message: "Couldn't find user", err });
    else {
      let len = orders.length;
      let orderCurInx = 0;
      let productsToDeliver = [];

      orders.forEach(order => {
        ++orderCurInx;

        order.products.forEach(item => {
          if (item.product.seller == anySellerId) {
            productsToDeliver.push(product);
          }
        });
      });

      if (len == orderCurInx) {
        return res.status(200).json({ orders });
      }
    }
  });
回答1

为了获得所有订单,在其中一种产品中,卖方ID与给定卖方ID相匹配的情况下,您可以使用$lookup$match管道组合的汇总:

db.getCollection('orders').aggregate([{
            $lookup: {
                from: "products",
                localField: "products.product",
                foreignField: "_id",
                as: "mappedProducts"
            }
        }, {
            $match: {
                "mappedProducts.seller": ObjectId("5f04bae5698dc66950a991a3")
            }
        }
    ]);

此方法的工作原理是$lookup将在指定的集合中搜索foreignField(在这种情况下为products)并将找到的product-文档添加到{{ 1}}-文档位于名为order的新数组属性下(您可以随意命名)。

剩下要做的就是匹配mappedProducts-id与给定的seller匹配的那些文档。