Per creare una query generica sarebbe necessario il framework di aggregazione in quanto ha alcuni utili operatori per aiutarti in questo. Per cominciare, dovresti convertire il documento incorporato in un array di coppie chiave/valore e quindi filtrare l'array sul campo chiave passando nelle impostazioni locali come parametro.
Ad esempio, converti il documento
"title": {
"en": "title en2",
"de": "title de2"
},
in un array
"title": [
{ "k": "en", '"v": "title en2" },
{ "k": "de", "v": "title de2" }
],
utilizzando $objectToArray
operatore. È quindi possibile filtrare questo array nel campo chiave utilizzando $filter
operatore come
{
'$filter': {
'input': { '$objectToArray': '$title' },
'cond': { '$eq': ['$$this.k', locale] }
}
}
dove la locale variabile è derivata dal parametro passato.
Una volta che hai l'array filtrato, per ottenere il campo del valore è necessario $arrayElemAt
operatore applicato sulla chiave del valore come
{
'$arrayElemAt': ['$title.v', 0]
}
Quindi alla fine dovrai eseguire una pipeline come questa:
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]
}
} }
]);
E con qualche refactoring:
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')
} }
]);