0

Imagine a document like below -

I want to return the PART along with Input's would be language say "ENG" or "FRA" or "GER"

Document-

{
    "_id" : ObjectId("56a5337f19d312a4156a3625"),
    "PartId" : "Part1",
    "Name" : "Name",
    "active" : "true",
    "attribute1" : "value1",
    "attribute2" : "value2",
    "LanguageData":[ 
        {
            "Language" : "ENG",
            "description" : "PARt1- English",
            "default" : "true"
        }, 
        {
            "Language" : "FRA",
            "description" : "Part1 in french",
            "supported" : "true"
        }, 
        {
            "Language" : "GER",
            "description" : "Part1 In German",
            "supported" : "false"
        }
    ]
}

If input is "ENG"

{
    "_id" : ObjectId("56a5337f19d312a4156a3625"),
    "PartId" : "Part1",
    "Name" : "Name",
    "active" : "true",
    "attribute1" : "value1",
    "attribute2" : "value2",
    "LanguageData":[ 
        {
            "Language" : "ENG",
            "description" : "PARt1- English",
            "default" : "true"
        }
    ]
}

If input is "GER" the out put should not return this document as "supported is false"

{}

If input is say "CHN" then default should be returned -

{
    "_id" : ObjectId("56a5337f19d312a4156a3625"),
    "PartId" : "Part1",
    "Name" : "Name",
    "active" : "true",
    "attribute1" : "value1",
    "attribute2" : "value2",
    "LanguageData":[ 
        {
            "Language" : "ENG",
            "description" : "PARt1- English",
            "default" : "true"
        }
    ]
}

I am not able to return sub document based on the conditions

Only the subdocument from array should be returned based on below conditions

1) So if language is present, then return that sub document.

2) If Sub-Document is not present always return default.

3) If Sub Document is present and not supported , do not return the whole document

chridam
  • 100,957
  • 23
  • 236
  • 235
  • What is the problem you are facing? – dikesh Feb 01 '16 at 08:08
  • 1
    Possible duplicate of [Retrieve only the queried element in an object array in MongoDB collection](http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection) – styvane Feb 01 '16 at 08:22
  • Can I use condition's in elemMatch during projection, slect specific language if present else select Default if language is not present? – AlokRagate Feb 01 '16 at 08:30

1 Answers1

2

To query the subdocument, you can do that through aggregate

db.document.aggregate([
    {$match: {'LanguageData.Language': 'GER'}},
    {$project: {
        LanguageData: {$filter: {
            input: '$LanguageData',
            as: 'LanguageData',
            cond: {$eq: ['$$LanguageData.Language', 'GER']}
        }}
    }}
])

For return the default data, the $ifNull could do that

db.document.aggregate([
    {$unwind: '$LanguageData'}, 
    {$match: {'LanguageData.Language': 'GER'}}, 
    {$project: 
       {LanguageData: 
          {Language: {$ifNull: ['$LanguageData.Language', 'CHN']}, 
           description: {$ifNull: ['$LanguageData.description', 'default description']}}}}
]);
zangw
  • 43,869
  • 19
  • 177
  • 214
  • Thanks for the reply, but I cannot match default rule when some language is not present "ZHN" is not present in the array of languages. – AlokRagate Feb 01 '16 at 08:25
  • @AlokRagate, I think `$ifNull` may meet your requirement to return the default value. – zangw Feb 01 '16 at 08:54
  • 1
    Thanks for the response , Although I am getting the below error-uncaught exception: aggregate failed: { "errmsg" : "exception: invalid operator '$filter'", "code" : 15999, "ok" : 0 } – AlokRagate Feb 01 '16 at 08:54
  • @AlokRagate, I just give you some sample codes here, for more details of the aggregation parameter, please go to the mongodb site.... – zangw Feb 01 '16 at 08:56
  • @AlokRagate, the `$filter` is added after version 3.2, what the version of mongo are you using? – zangw Feb 01 '16 at 09:03
  • The below fails to return data when there is no matchin Language, and I would still want to return the default sub documnet. db.TestTopics.aggregate([ { $unwind : "$LanguageData" }, { $match: { "LanguageData.language": 'GER' }}, { $project: { LanguageData: { $ifNull: ["$description", "Unspecified"]} } } ]); – AlokRagate Feb 01 '16 at 09:22