MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDB списъци - вземете всеки N-ти елемент

Изглежда, че вашият въпрос ясно задава "вземи всеки n-ти екземпляр", което наистина изглежда като доста ясен въпрос.

Операции за заявки като .find() наистина може да върне документа само „какъвто е“ с изключение на общото поле „избор“ в проекцията и оператори като позиционен $ оператор за съответствие или $elemMatch които позволяват единичен съответстващ елемент на масив.

Разбира се, има $slice , но това просто позволява „избор на диапазон“ в масива, така че отново не се прилага.

„Единствените“ неща, които могат да променят резултат на сървъра, са .aggregate() и .mapReduce() . Първият не "играе много добре" с "нарязване" на масиви по никакъв начин, поне не с "n" елемента. Въпреки това, тъй като аргументите "function()" на mapReduce са базирана на JavaScript логика, тогава имате малко повече място за игра.

За аналитични процеси и „само“ за аналитични цели просто филтрирайте съдържанието на масива чрез mapReduce, като използвате .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
)

На този етап това наистина е просто "изпълняващ JavaScript", но ако това е само за анализ/тестване, тогава няма нищо лошо в концепцията. Разбира се, резултатът не е "точно" как е структуриран вашият документ, но е толкова близо до факсимиле, колкото mapReduce може да получи.

Другото предложение, което виждам тук, изисква създаване на нова колекция с всички елементи „денормализирани“ и вмъкване на „индекс“ от масива като част от unqique _id ключ. Това може да произведе нещо, което можете да заявите директно, но за „всеки n-ти елемент“ пак ще трябва да направите:

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

Така че разработете и осигурете стойността на индекса на „всеки n-ти елемент“, за да получите „всеки n-ти елемент“. Така че това наистина не изглежда да реши проблема, който беше зададен.

Ако изходната форма изглеждаше по-желана за вашите "тестващи" цели, тогава по-добра последваща заявка за тези резултати би била използването на тръбопровода за агрегиране с $redact

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

Това поне използва „логическо условие“ почти същото като това, което беше приложено с .filter() преди просто да изберете елементите на "n-тия индекс", без да изброявате всички възможни стойности на индекса като аргумент на заявката.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDb:Как да вмъкна допълнителен обект в колекция от обекти в golang?

  2. MongoDB $atanh

  3. Използване на методи на клас MongoEngine Document за персонализирано валидиране и предварително запазване на кукички

  4. Как да активирам удостоверяване на MongoDB чрез Docker?

  5. Mongoid Association Създаване на (нежелани) записи