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

Listas de MongoDB:obtenga cada N-ésimo elemento

Parece que su pregunta claramente hizo "obtener cada enésima instancia", lo que parece una pregunta bastante clara.

Operaciones de consulta como .find() realmente solo puede devolver el documento "tal cual" con la excepción del campo general "selección" en proyección y operadores como posicional $ operador de coincidencia o $elemMatch que permiten un elemento de matriz coincidente singular.

Por supuesto, hay $slice , pero eso solo permite una "selección de rango" en la matriz, por lo que nuevamente no se aplica.

Las "únicas" cosas que pueden modificar un resultado en el servidor son .aggregate() y .mapReduce() . El primero no "juega muy bien" con arreglos "cortados" de ninguna manera, al menos no por "n" elementos. Sin embargo, dado que los argumentos "función()" de mapReduce son una lógica basada en JavaScript, entonces tiene un poco más de espacio para jugar.

Para procesos analíticos, y "solo" con fines analíticos, simplemente filtre el contenido de la matriz a través de mapReduce usando .filter() :

db.collection.mapReduce(
    function() {
        var id = this._id;
        delete this._id;

        // filter the content of "instances" to every 3rd item only
        this.instances = this.instances.filter(function(el,idx) {
            return ((idx+1) % 3) == 0;
        });
        emit(id,this);
    },
    function() {},
    { "out": { "inline": 1 } } // or output to collection as required
)

En realidad, es solo un "ejecutor de JavaScript" en este punto, pero si esto es solo para análisis/pruebas, entonces, en general, no hay nada malo con el concepto. Por supuesto, el resultado no es "exactamente" cómo está estructurado su documento, pero es lo más cercano a un facsímil que puede obtener mapReduce.

La otra sugerencia que veo aquí requiere crear una nueva colección con todos los elementos "desnormalizados" e insertar el "índice" de la matriz como parte del único _id llave. Eso puede producir algo que puede consultar directamente, pero para "cada n-ésimo elemento" aún tendría que hacer:

db.resultCollection.find({
     "_id.index": { "$in": [2,5,8,11,14] } // and so on ....
})

Así que calcule y proporcione el valor de índice de "cada n-ésimo elemento" para obtener "cada n-ésimo elemento". Así que eso realmente no parece resolver el problema que se planteó.

Si el formulario de salida parecía más deseable para sus propósitos de "prueba", entonces una mejor consulta posterior sobre esos resultados sería usar la canalización de agregación, con $redact

db.newCollection([
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [ 
                    { "$mod": [ { "$add": [ "$_id.index", 1] }, 3 ] },
                0 ]
            },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}
])

Eso al menos usa una "condición lógica" muy similar a la que se aplicó con .filter() antes de simplemente seleccionar los elementos del "índice n" sin enumerar todos los valores de índice posibles como argumento de consulta.