0

I've been having trouble trying to query for a deeply nested subdocument while using Mongoose. My DB structure is like this:

{
    "_id": "662aa6ccae109745e30dc664",
    "username": "username",
    "email": "[email protected]",
    "lists": [
        {
            "_id": "662aa6dbae109745e30dc66a"
            "name": "list",
            "content": [
                {
                    "_id": "662aa6eeae109745e30dc670"
                    "name": "product",
                    "quantity": 30,
                    "brands": [],
                }
            ],
        },
    ],
}

All I want is to query for the product _id ("_id": "662aa6eeae109745e30dc670" for example) and get the list and user _id("_id": "662aa6dbae109745e30dc66a" and "_id": "662aa6ccae109745e30dc664" respectively, on this example).

I've tried queryin for:

const user = await findOne({ 'lists.content._id': '662aa6eeae109745e30dc670' })

But this returns the whole user object. How can I query so it's return only the product object (since I can use the 'child.parent()' method to get the listId)

2 Answers 2

0

Use an aggregation pipeline so you can $unwind each array lists & then lists.content. Then match on the criteria for lists.content._id and project the fields you want.

db.collection.aggregate([
  { $unwind: "$lists" },
  { $unwind: "$lists.content" },
  {
    $match: {
      "lists.content._id": "662aa6eeae109745e30dc670"
    }
  },
  {
    $project: {
      // _id will be included anyway
      list_id: "$lists._id",
      content_id: "$lists.content._id"
    }
  },
  // limit to just one doc if that's a requirement; NOT recommended
  { $limit: 1 }
])

Result:

[
  {
    "_id": "662aa6ccae109745e30dc664",
    "content_id": "662aa6eeae109745e30dc670",
    "list_id": "662aa6dbae109745e30dc66a"
  }
]

Mongo Playground


If you want the _id fields as they were nested in the original doc, use this $project stage instead:

  {
    $project: {
      "lists._id": 1,
      "lists.content._id": 1
    }
  }

Result:

[
  {
    "_id": "662aa6ccae109745e30dc664",
    "lists": {
      "_id": "662aa6dbae109745e30dc66a",
      "content": {
        "_id": "662aa6eeae109745e30dc670"
      }
    }
  }
]
Sign up to request clarification or add additional context in comments.

Comments

0
db.collection.aggregate([
  {
    $unwind: "$lists" 
  },
  {
    $unwind: "$lists.content"
  },
  {
    $match: {
      "lists.content._id": ObjectId("662aa6eeae109745e30dc670")
    }
  },
  {
    $project: {
      _id: 0,
      user_id: "$_id",
      list_id: "$lists._id",
      product_id: "$lists.content._id" 
    }
  }
])

Result:

[
  {
    user_id: ObjectId("662aa6ccae109745e30dc664"),
    list_id: ObjectId("662aa6dbae109745e30dc66a"),
    product_id: ObjectId("662aa6eeae109745e30dc670")
  }
]

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.