Mongoose 如何过滤填充字段

Ama*_*sal 6 mongoose mongodb mongodb-query mongoose-populate

我有订单和用户,我想通过 Mongoose Populate 或其他方式按用户电话号码查找订单,我该怎么做?

Order (_id, item, user_id)
User (_id, email, phone)

const orders = await Order.find({}).populate({path: 'user', select: 'phone'})
Run Code Online (Sandbox Code Playgroud)

我想要类似的东西 (user.phone='xxxxxx') 我无法弄清楚。

Sau*_*try 9

使用猫鼬:

  • 首先它会找到所有订单

  • 仅填充与电话号码匹配的用户,其他 user_id 将显示 null 。

  • 然后通过 user_id 不为空过滤订单

     var user_orders = await Order.find()
     .populate({
      path:'user_id',
      match: {'phone': {$eq: phoneNumber}}
     })
     .then((orders)=>orders.filter((order=>order.user_id !=null)));
    
    Run Code Online (Sandbox Code Playgroud)

使用 mongodb 聚合:

  • 首先使用查找阶段和用户集合来获取用户详细信息
  • 展开用户(将用户数组从第一查看阶段转换为用户对象)
  • 然后使用匹配阶段按用户电话号码查找文档。

聚合管道:查找=>展开=>匹配

var user_orders = await db.order.aggregate([
{
  '$lookup': {
    'from': 'user',
    'localField': 'user_id',
    'foreignField': '_id',
    'as': 'user'
  }
},
{
    '$unwind': {
      'path': '$user'
     }
},
{
  '$match': {
    'user.phone': phoneNumber
  }
} 
]);
Run Code Online (Sandbox Code Playgroud)


小智 2

更简单的解决方案

首先从用户集合中查找具有给定电话号码的 UserInstance。

db.user.find({phone: PhoneNumber})
Run Code Online (Sandbox Code Playgroud)

然后从订单集合中查找该用户的 OrderInstances。

db.order.find({user_id: userInstance._id})
Run Code Online (Sandbox Code Playgroud)

为什么不使用填充

Populate 是 Mongoose 库方法,而不是原生 MongoDb 方法。要使用 Populate,您必须相应地定义您的模式。

var user = Schema({
    _id: Schema.Types.ObjectId,
    email: String,
    phone: Number,
});

var order = Schema({
    _id: Schema.Types.ObjectId,
    item: String,
    user_id: { type: Schema.Types.ObjectId, ref: 'user' }
});
Run Code Online (Sandbox Code Playgroud)

如果您像这样定义模型,然后使用 populate 来查找用户订单。然后发生以下步骤:

  1. 查找所有订单并填充用户。

    db.order.find().populate('user_id')

  2. 使用电话号码过滤用户的订单。

这确实效率很低,因为它每次都获取所有订单,而不是使用数据库高效查询。mongoDB 原生的 $lookup 也是如此。