sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB-listor - få varje N:te objekt

Det verkar som att din fråga tydligt ställdes "få var n:e instans", vilket verkar vara en ganska tydlig fråga.

Fråga operationer som .find() kan egentligen bara returnera dokumentet "som det är" med undantag för det allmänna fältet "selektion" i projektion och operatorer som positional $ match operator eller $elemMatch som tillåter ett singular matchat array-element.

Naturligtvis finns det $slice , men det tillåter bara ett "intervallval" på arrayen, så återigen gäller det inte.

De "enda" sakerna som kan modifiera ett resultat på servern är .aggregate() och .mapReduce() . Den förra "spelar inte särskilt bra" med att "skiva" arrayer på något sätt, åtminstone inte med "n" element. Men eftersom "function()"-argumenten i mapReduce är JavaScript-baserad logik, så har du lite mer utrymme att leka med.

För analytiska processer och för analytiska ändamål "endast" filtrera sedan arrayinnehållet via mapReduce med .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
)

Det är egentligen bara en "JavaScript-löpare" vid det här laget, men om detta bara är för analys/testning så är det inget generellt fel på konceptet. Naturligtvis är resultatet inte "exakt" hur ditt dokument är strukturerat, men det är så nära en fax som mapReduce kan komma.

Det andra förslaget jag ser här kräver att man skapar en ny samling med alla objekt "denormaliserade" och infogar "index" från arrayen som en del av den unika _id nyckel. Det kan leda till något du kan fråga direkt, men för "varje n:e artikel" måste du fortfarande göra:

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

Så räkna ut och ange indexvärdet för "varje n:te post" för att få "varje n:te post". Så det verkar inte riktigt lösa problemet som ställdes.

Om utdataformen verkade mer önskvärd för dina "testnings"-ändamål, skulle en bättre efterföljande fråga om dessa resultat vara att använda aggregeringspipelinen, med $redact

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

Det använder åtminstone ett "logiskt villkor" ungefär som det som tillämpades med .filter() innan för att bara välja "n:te index"-objekten utan att lista alla möjliga indexvärden som ett frågeargument.



  1. RuntimeError:Uppgift kopplad till en annan slinga

  2. push nytt värde till mongodb inre array - mongodb/php

  3. Kommandoradsfråga i Java

  4. Mongo-fråga i python om jag använder variabel som värde