За да създадете обща заявка, ще ви е необходима рамката за агрегиране, тъй като има някои удобни оператори, които да ви помогнат с това. Като начало ще трябва да преобразувате вградения документ в масив от двойки ключ/стойност и след това да филтрирате масива по ключовото поле, предаващо локала като параметър.
Например конвертирайте документа
"title": {
"en": "title en2",
"de": "title de2"
},
към масив
"title": [
{ "k": "en", '"v": "title en2" },
{ "k": "de", "v": "title de2" }
],
използвайки $objectToArray
оператор. След това можете да филтрирате този масив в ключовото поле, като използвате $filter
оператор като
{
'$filter': {
'input': { '$objectToArray': '$title' },
'cond': { '$eq': ['$$this.k', locale] }
}
}
където локалът на променливата се извлича от предадения параметър.
След като имате филтрирания масив, получаването на полето за стойност изисква $arrayElemAt
оператор, приложен към стойностния ключ като
{
'$arrayElemAt': ['$title.v', 0]
}
Така че в крайна сметка ще трябва да стартирате конвейер като този:
var locale = 'en';
db.cs.aggregate([
{ '$match': { "cID" : "00001" } },
{ '$addFields': {
'title': {
'$filter': {
'input': { '$objectToArray': '$title' },
'cond': { '$eq': ['$$this.k', locale] }
}
},
'desc': {
'$filter': {
'input': { '$objectToArray': '$desc' },
'cond': { '$eq': ['$$this.k', locale] }
}
}
} },
{ '$addFields': {
'title': {
'$arrayElemAt': ['$title.v', 0]
},
'desc': {
'$arrayElemAt': ['$desc.v', 0]
}
} }
]);
И с известно преработване:
var locale = 'en';
var getFilterOperatorExpression = function (field) {
return {
'$filter': {
'input': { '$objectToArray': '$'+ field },
'cond': { '$eq': ['$$this.k', locale] }
}
}
};
var getValueOperatorExpression = function (field) {
return {
'$arrayElemAt': ['$'+ field +'.v', 0]
}
};
db.cs.aggregate([
{ '$match': { "cID" : "00001" } },
{ '$addFields': {
'title': getFilterOperatorExpression('title'),
'desc': getFilterOperatorExpression('desc'),
} },
{ '$addFields': {
'title': getValueOperatorExpression('title'),
'desc': getValueOperatorExpression('desc')
} }
]);