Anton Shuvalov
Anton Shuvalov

Reputation: 3671

Get the only one sub-subdocument

I have a collection of documents like this:

{
  "_id" : ObjectId("532d4e7d569c9e4574d5156e"),
  "title" : "Book Title"
  "author" : "Book Author",
  "owner" : "532d4e7c569c9e4574d51568",
  "pages" : [
    {
      "texts" : [
        {
          "_id" : ObjectId("532d4e7d569c9e4574d51572"),
          "paragraphs" : [ ],
          "format" : [ ],
          "position" : {
            "y" : 0,
            "x" : 0
          }
        }
      ],
      "images" : [
        {
          "_id" : ObjectId("532d4e7f569c9e4574d51573"),
          "position" : {
            "y" : 0,
            "x" : 0
          }
        }
      ],
    },
    {
      "_id" : ObjectId("532d4e7d569c9e4574d51571"),
      "videos" : [ ],
      "audios" : [ ],
      "images" : [ ],
      "texts" : [ ],
      "animations" : [ ]
    }
  ]
}

and I want to get the only text subdocument with _id:

db.projects.find({'pages.texts._id': ObjectId("532d4e7d569c9e4574d51572")}, {'pages.$.texts.$': 1}).pretty()

but it's not works.

I want to get only this part of document:

{
  "_id" : ObjectId("532d4e7d569c9e4574d51572"),
  "paragraphs" : [ ],
  "format" : [ ],
  "position" : {
    "y" : 0,
    "x" : 0
  }
}

Upvotes: 0

Views: 112

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151112

From the documentation for the positional $ operator:

The positional $ operator limits the contents of the field that is included in the query results to contain the first matching element. To specify an array element to update, see the positional $ operator for updates.

You have two arrays. First is pages. Second is texts.

The "position" is only matched on the first array and not again. You can do this with .aggregate() :

Projects.aggregate([
       // Match documents
       { "$match": {
           "pages.texts._id": ObjectId("532d4e7d569c9e4574d51572")
       }},

       // Unwind the pages array
       { "$unwind": "$pages" },

       // Unwind the "texts" array
       { "$unwind": "$pages.texts" },

       // Filter array
       { "$match": {
           "pages.texts._id": ObjectId("532d4e7d569c9e4574d51572")
       }},

       // Re-form
       { "$group": {
           "_id": "$_id",
           "texts": { "$push": "$pages.texts"  }
       }}
    ],
    function(err, res) {
       // do things with res or err here
})

And the mongoose documentation.

More on aggregation operators.

More reading here

Upvotes: 1

Related Questions