Search code examples
node.jsmongodbmongoosemern

Find array of object that refers to another model by their id


const mongoose = require("mongoose");

const bidSchema = new mongoose.Schema({
  auctionId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "auctionRooms",
    required: true,
  },
  bids: [
    {
      buyerId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "User",
        required: true,
      },
      amount: {
        type: Number,
        required: true,
      },
    },
  ],
});

const Bid = mongoose.model("Bid", bidSchema);
exports.Bid = Bid;

I want to search for bids based on buyerId inside the bids array. Here is what I tried.

const getBidsForSpecificUserAuction = async (req, res) => {
  const { auctionId, buyerId } = req.params;
  const findLastBid = await Bid.findOne({
    auctionId,
    "bids.buyerId": buyerId,
  })
    .populate({
      path: "bids.buyerId",
      model: "User",
      select: "-__v -password  -email -date",
    })
    .sort("_bids._id");
  if (!findLastBid) {
    return res.status(404).send("Operation failed, Please try again");
  } else {
    console.log(findLastBid.bids);
    res.send(findLastBid);
  }
};

It returns all the bids inside the auction based on the acutionId correctly but not the one with the correct buyerId. 63947eb56b063c4b9135b8e5 is the buyerId passed to the router. So what I want is to return the bids which buyerId is 63947eb56b063c4b9135b8e5.

{
    "_id": "63a0ded968fbb982e2d9ff95",
    "auctionId": "63a0c001033638ec6cd2d3cb",
    "bids": [
        {
            "buyerId": {
                "_id": "63947eb56b063c4b9135b8e5",
                "firstName": "Buyer 3",
                "lastName": "test",
                "phoneNumber": "9799087",
                "role": "63890be8956f88ff5d891d87"
            },
            "amount": 50,
            "_id": "63a0ded968fbb982e2d9ff96"
        },
        {
            "buyerId": {
                "_id": "63893782b607e201fcf854da",
                "firstName": "Buyer",
                "lastName": "Test",
                "phoneNumber": "96087",
                "role": "63890be8956f88ff5d891d87"
            },
            "amount": 150,
            "_id": "63a0dedc68fbb982e2d9ffa1"
        },
        {
            "buyerId": {
                "_id": "63947eb56b063c4b9135b8e5",
                "firstName": "Buyer 3",
                "lastName": "test",
                "phoneNumber": "9908",
                "role": "63890be8956f88ff5d891d87"
            },
            "amount": 200,
            "_id": "63a0dee068fbb982e2d9ffaf"
        },
        {
            "buyerId": {
                "_id": "63893782b607e201fcf854da",
                "firstName": "Buyer",
                "lastName": "Test",
                "phoneNumber": "9237087",
                "role": "63890be8956f88ff5d891d87"
            },
            "amount": 250,
            "_id": "63a0dee368fbb982e2d9ffc0"
        },
]
}

The goal is to search for a bid that has both the auctionId and the buyerId that is passed to the controller


Solution

  • You can do it with Aggregation framework:

    db.collection.aggregate([
      {
        "$match": {
          "auctionId": "63a0c001033638ec6cd2d3cb"
        }
      },
      {
        "$set": {
          "bids": {
            "$filter": {
              "input": "$bids",
              "cond": {
                "$eq": [
                  "$$this.buyerId._id",
                  "63947eb56b063c4b9135b8e5"
                ]
              }
            }
          }
        }
      }
    ])
    

    Working example