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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.