sql >> Base de Datos >  >> NoSQL >> MongoDB

Consulta de datos localizados en MongoDB

Para crear una consulta genérica, se necesitaría el marco de agregación, ya que tiene algunos operadores útiles para ayudarlo con esto. Para empezar, necesitaría convertir el documento incrustado en una matriz de pares clave/valor y luego filtrar la matriz en el campo clave pasando la configuración regional como parámetro.

Por ejemplo, convertir el documento

  "title": {
    "en": "title en2",
    "de": "title de2"
  },

a una matriz

  "title": [
    { "k": "en", '"v": "title en2" },
    { "k": "de", "v": "title de2" }
  ],

usando $objectToArray operador. Luego puede filtrar esta matriz en el campo clave usando el $filter operador como

{
    '$filter': {
        'input': { '$objectToArray': '$title' },
        'cond': { '$eq': ['$$this.k', locale] }
    }
}

donde la configuración regional de la variable se deriva del parámetro pasado.

Una vez que tenga la matriz filtrada, obtener el campo de valor requiere el $arrayElemAt operador aplicado en la clave de valor como

{ 
    '$arrayElemAt': ['$title.v', 0]
}

Entonces, al final, tendrá que ejecutar una canalización como esta:

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]
        }
    } }
]);

Y con algo de refactorización:

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')
    } }
]);