0

Having document in collection test as follow:

{a:1, list:[{lang:"en", value:"Mother"}, {lang:"de", value:"Mutter"}] }
{a:2, list:[{lang:"en", value:"Iddqd"}] }

I would like build query that tries to match list.value to selected language, but if it absent then return any-available-item of list, so for example above and for query language de i need get $projection as:

{a:1, label:"Mutter"},
{a:2, label:"Iddqd"} //since no label matched 'de' let's select any available

Server version: MongoDB 3.2+

5
  • 1
    Can you please elaborate on why you should get {a:2, label:"Iddqd"} for the second document? Commented Sep 29, 2016 at 16:13
  • Does the maximum length of your list always equal 2? Commented Sep 29, 2016 at 16:15
  • @Styvane - just updated, in short "Iddqd" - is any available item. List is rather short - not exceeding 10 Commented Sep 29, 2016 at 16:24
  • What is your MongoDB version? Commented Sep 29, 2016 at 16:25
  • @Styvane - Mongo 3.2+ Commented Sep 29, 2016 at 16:26

1 Answer 1

1

You need to filter the list, assign the result to a variable using the $let operator. If the variable is an empty list, you return a given value using the $arrayElemAt operator. In this case, I simply return the first sub-document.

db.coll.aggregate([
    { "$project": { 
        "a": 1, 
        "label": { 
            "$let": { 
                "vars": { 
                    "values": {
                        "$arrayElemAt": [ 
                            { "$filter": { 
                                "input": "$list", 
                                "as": "lst", 
                                "cond": { "$eq": [ "$$lst.lang", "de" ] }
                            }}, 
                            0 
                        ] 
                    } 
                }, 
                "in": { 
                    "$ifNull": [ 
                        "$$values.value", 
                        { "$let": { 
                            "vars": { 
                                "default": { 
                                    "$arrayElemAt": [ "$list", 0 ]
                                } 
                            }, 
                            "in": "$$default.value" 
                        }}
                    ]
                }
            }
        }
    }}
])
Sign up to request clarification or add additional context in comments.

2 Comments

Not sure why, but $filter returns both items of array that contains de and en as well
@Dewfy I've update my answer. Will add more explanation when have a little time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.