MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Listes MongoDB - obtenez chaque nième élément

Il semble que votre question demandait clairement "obtenir chaque nième instance", ce qui semble être une question assez claire.

Opérations de requête comme .find() ne peut vraiment que renvoyer le document "tel quel" à l'exception du champ général "sélection" dans la projection et des opérateurs tels que le positionnel $ opérateur de correspondance ou $elemMatch qui autorisent un élément de tableau correspondant singulier.

Bien sûr, il y a $slice , mais cela permet simplement une "sélection de plage" sur le tableau, donc encore une fois ne s'applique pas.

Les "seules" choses qui peuvent modifier un résultat sur le serveur sont .aggregate() et .mapReduce() . Le premier ne "joue pas très bien" avec les tableaux "découpés" de quelque manière que ce soit, du moins pas par "n" éléments. Cependant, puisque les arguments "function()" de mapReduce sont une logique basée sur JavaScript, vous avez un peu plus de place pour jouer avec.

Pour les processus analytiques, et à des fins analytiques "uniquement", filtrez simplement le contenu du tableau via mapReduce en utilisant .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
)

C'est vraiment juste un "coureur JavaScript" à ce stade, mais si c'est juste pour l'analyse/les tests, il n'y a généralement rien de mal avec le concept. Bien sûr, la sortie n'est pas "exactement" la façon dont votre document est structuré, mais c'est aussi proche d'un fac-similé que mapReduce peut l'obtenir.

L'autre suggestion que je vois ici nécessite de créer une nouvelle collection avec tous les éléments "dénormalisés" et d'insérer "l'index" du tableau dans le cadre de l'unqique _id clé. Cela peut produire quelque chose que vous pouvez interroger directement, mais pour "chaque nième élément", vous auriez encore à faire :

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

Donc, calculez et fournissez la valeur d'index de "chaque nième élément" afin d'obtenir "chaque nième élément". Cela ne semble donc pas vraiment résoudre le problème qui a été posé.

Si le formulaire de sortie semblait plus souhaitable pour vos objectifs de "test", alors une meilleure requête ultérieure sur ces résultats utiliserait le pipeline d'agrégation, avec $redact

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

Cela utilise au moins une "condition logique" à peu près la même que celle appliquée avec .filter() avant de simplement sélectionner les éléments "nième index" sans lister toutes les valeurs d'index possibles comme argument de requête.