4

I have array in subdocument like this

    {
    "_id" : ObjectId("512e28984815cbfcb21646a7"),
    "descDay" : [
        {
            "language" : "en",
            "desc": "day description"
        },
        {
            "language" : "es",
            "desc": "descripcion del dia"
        }
    ]
}

I want to filter the subdocuments by language. I can do that like this

db.test.aggregate([
    { $project: {
        descDay: {$filter: {
            input: '$list',
            as: 'item',
            cond: {$gt: ['$$item.language', 'en']}
        }}
    }}
])

that would give me something like

{
  "_id" : ObjectId("512e28984815cbfcb21646a7"),
   "descDay" : [
      {
        "language" : "en",
        "desc": "day description"
       }]
}

but I need descDay to be a document not an array, something like this:

   {
      "_id" : ObjectId("512e28984815cbfcb21646a7"),
       "descDay" : 
          {
            "language" : "en",
            "desc": "day description"
           }
    }

how can I get that?

chridam
  • 100,957
  • 23
  • 236
  • 235
irokhes
  • 1,643
  • 1
  • 14
  • 20

1 Answers1

4

You can use $unwind to unwind the single-element descDay array into an object:

db.test.aggregate([
    { $project: {
        descDay: {$filter: {
            input: '$descDay',
            as: 'item',
            cond: {$eq: ['$$item.language', 'en']}
        }}
    }},
    { $unwind: '$descDay' }
])

Or, as @chridam mentioned, you can use $arrayElemAt in the $project and directly project the first element:

db.test.aggregate([
    { $project: {descDay: {$arrayElemAt: [
        {$filter: {
            input: '$descDay',
            as: 'item',
            cond: {$eq: ['$$item.language', 'en']}
        }}, 0]
    }}}
])

Either way the output is:

{ 
    "_id" : ObjectId("512e28984815cbfcb21646a7"), 
    "descDay" : {
        "language" : "en", 
        "desc" : "day description"
    }
}

Note that I had to fix a couple problems in your original query:

  1. '$list' to '$descDay'
  2. $gt to $eq
JohnnyHK
  • 305,182
  • 66
  • 621
  • 471