5

I have Orders and Users and i want to find orders by User phone number via Mongoose Populate or something else how do i do that ?

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

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

I want something like that where (user.phone='xxxxxx') i am unable to figure it out.

Promila Ghosh
  • 389
  • 4
  • 12
Khanakia
  • 723
  • 1
  • 8
  • 20
  • Look at using $lookup on the collection instead of trying to filter on populate, as suggested here: https://stackoverflow.com/questions/11303294/querying-after-populate-in-mongoose – jacobedawson Jul 20 '18 at 13:37

2 Answers2

6

Using 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)));
    

Using mongodb aggregation :

  • first use lookup stage with user collection to get user details
  • unwind user (to convert user array to user object from first look stage)
  • then use match stage to find documents by users phone number .

aggregation pipeline : 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
  }
} 
]);
Saurabh Mistry
  • 12,833
  • 5
  • 50
  • 71
1

A Simpler Solution

First find UserInstance from User Collection with given phone number.

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

Then find OrderInstances from Order Collection for that user.

db.order.find({user_id: userInstance._id})

Why Not To Use Populate

Populate is Mongoose library mehtod and not native MongoDb method. To make use of Populate you will have to define your schemas accordingly.

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

If you define models like this and then use populate to find user orders. Then following steps occur:

  1. Find all orders and Populate with users.

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

  2. Filter orders for the user with phone number.

This is really inefficient as it is fetching all the orders every time and not using DB efficient queries. Same will be the case with $lookup which is native to mongoDB.

cheekujha
  • 781
  • 4
  • 12