Mongoose如何在populate字段上进行过滤

5
我有订单和用户,我想通过 Mongoose Populate 或其他方式按用户电话号码查找订单,该如何操作?
Order (_id, item, user_id)
User (_id, email, phone)

const orders = await Order.find({}).populate({path: 'user', select: 'phone'})

我希望能够实现像这样的功能,即(user.phone='xxxxxx'),但我无法理解它的含义。

请尝试在集合上使用$lookup,而不是尝试在populate上进行过滤,就像这里建议的那样:https://dev59.com/PGgu5IYBdhLWcg3wdG6o - jacobedawson
2个回答

6

使用Mongoose:

  • first it will find all orders

  • populate only user that match with phone number other user_id will display null .

  • then filter orders by user_id is not null

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

使用mongodb聚合操作:

  • 首先使用lookup阶段与用户集合结合以获取用户详细信息。
  • 展开用户(将第一个lookup阶段中的用户数组转换为用户对象)
  • 然后使用match阶段按用户手机号查找文档。

聚合管道:lookup => unwind => match

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

1

更简单的解决方案

首先根据给定的电话号码在用户集合中查找UserInstance。

db.user.find({phone: PhoneNumber})

然后从该用户的订单集合中查找订单实例。
db.order.find({user_id: userInstance._id})

为什么不应该使用 Populate

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' }
});

如果您定义模型并使用populate查找用户订单,则会发生以下步骤:
1. 查找所有订单并与用户进行关联。 db.order.find().populate('user_id')
2. 为具有电话号码的用户过滤订单。
这样做非常低效,因为它每次都会获取所有订单,并且没有使用数据库高效的查询方式。$lookup也是如此,这是mongoDB本地支持的功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接