Home > Blockchain >  MongoDB (Mongoose) - Get only records where nested item is equal to a value
MongoDB (Mongoose) - Get only records where nested item is equal to a value

Time:10-29

I searched a lot, tried several ways, but nothing works.

I have this in mongo:

{
    id: ObjectId("1234567890"),
    answers: [{
        id: 111,
        deleted:0
    },
    {
        id: 222,
        deleted:0
    },
    {
        id: 333,
        deleted:1
    }]
},
{
    id: ObjectId("0987654321"),
    answers: [{
        id: 111,
        deleted:0
    },
    {
        id: 222,
        deleted:1
    },
    {
        id: 333,
        deleted:1
    }]
}

I want the document with ObjectId("1234567890"), and only the answers with delete = 1 ( only the id 333).

I have tryied this:

  var query = chatbotMongoModel.find(
                { _id: "1234567890" },
                { answers: {$elemMatch: {deleted: "1"}}}
            )

but returns all the answers.. Could you give me some help plase?

thanks!

Rafael

CodePudding user response:

One way of doing this is using mongodb aggregation framework.

var result = await chatbotMongoModel.aggregate([
  {
    $match: {
      id: "1234567890"
    }
  },
  {
    "$unwind": {
      path: "$answers"
    }
  },
  {
    $match: {
      "answers.deleted": 1
    }
  },
  {
    $group: {
      _id: "$id",
      answers: {
        $push: "$answers"
      },
      allFields: {
        $first: "$$ROOT"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$allFields",
          {
            "answers": "$answers"
          }
        ]
      }
    }
  }
])

Note that in your sample documents you have id but you use _id in your query, they must match. Also deleted data type is number in sample documents, but you use string value in your query.

Running mongoplayground.

Another alternative solution:

var result = await chatbotMongoModel.aggregate([
  {
    $match: {
      id: "1234567890"
    }
  },
  {
    $addFields: {
      "answers": {
        $filter: {
          input: "$answers",
          as: "answer",
          cond: {
            $eq: [
              "$$answer.deleted",
              1
            ]
          }
        }
      }
    }
  }
])

mongoplayground

CodePudding user response:

Thanks for the answers! I found a solution, and im posting here if someone needs this too...

var query = model.aggregate([
        { $match: { '_id': mongoose.Types.ObjectId("1234567890") } },
        {
          $project: {
            answer: {
              $filter: {
                input: "$answer",
                as: "f",
                cond: { $eq: ["$$f.deleted", 1] }
              }
            }
          }
        }
      ])

regards!

  • Related