Marko Švaljek
Marko Švaljek

Reputation: 2101

How to find documents that contain property inside array in mongo

After reading all online resources that I could think of still unable to think of solution to this one. Basically, I have documents with following data in mongo:

// 1
{
  a: {
    b: {
      languages: {
        en: {
          text: "en",
          type: "secret"
        },
        de: {
          text: "de"
        }
      }
    }
  }
}
//2
{
  a: {
    b: {
      languages: {
        fr: {
          text: "fr"
        },
        de: {
          text: "de",
          type: "public"
        }
      }
    }
  }
},

this returns me whatever the first document is, it doesn't matter when I change the secret to whatever:

db.products.findOne({"a.b.languages": {$exists: {$elemMatch: {"type": {$eq: "secret"}}}}}, {"key": 1, "a.b.languages": 1})

What I'm after is all the documents that contain languages of certain type - this field is also optional. How could I construct such a query?

Also if this problem is standard please provide me info so that I could update the question.

Upvotes: 1

Views: 603

Answers (1)

mickl
mickl

Reputation: 49985

The problem you are experiencing here is that there's no array in your documents - you just have nested objects with unknown keys. To query that kind of structure you need to convert those nested documents into an array using $objectToArray operator.

db.col.aggregate([
    {
        $addFields: {
            languages: { $objectToArray: "$a.b.languages" }
        }
    },
    {
        $match: { "languages.v.type": "secret" }
    },
    {
        $project: { languages: 0 }
    }
])

above code will convert a.b.languages path into an array of keys and values (object with k and v fields) so you can query directly referencing languages.v.type then. $addFields and $project are used to generate and then remove temporary field that can be queried.

Upvotes: 2

Related Questions