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

Mongo заявка за сортиране по отделен брой

Това наистина (все още) се обработва най-добре от множество заявки, тъй като MongoDB наистина „все още“ няма наистина ефективните оператори, за да направи това.

Можете обаче да направите нещо подобно с MongoDB 3.2, но има очевидни „уловки“:

db.Books.aggregate([
    { "$group": {
        "_id": "$company",
        "count": { "$sum": 1 },
        "urls": {
            "$push": "$url"
        }
    }},
    { "$sort": { "count": -1 } },
    { "$limit": 10 },
    { "$project": {
        "count": 1,
        "urls": { "$slice": ["$urls",0, 3] }
    }}
])

И очевидният проблем е, че независимо от всичко, вие все още добавяте всички на съдържанието „url“ в групирания масив. Това има потенциал да надхвърли ограничението за BSON от 16MB. Може и да не е, но все пак е малко разточително да добавяте „цялото“ съдържание, когато искате само „три“ от тях.

Така че дори тогава вероятно е по-практично просто да направите заявка за „url адресите“ отделно за всеки от първите 10 резултата.

Ето списък за node.js, който демонстрира:

var async = require('async'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient;

MongoClient.connect("mongodb://localhost/test",function(err,db) {

    if (err) throw err;

    // Get the top 10
    db.collection("Books").aggregate(
        [
            { "$group": {
                "_id": "$company",
                "count": { "$sum": 1 }
             }},
             { "$sort": { "count": -1 } },
             { "$limit": 10 }
        ],function(err,results) {
            if (err) throw err;

            // Query for each result and map query response as urls
            async.map(
                results,
                function(result,callback) {
                    db.collection("Books").find({ 
                       "company": result.company 
                    }).limit(3).toArray(function(err,items) {
                        result.urls = items.map(function(item) { 
                            return item.url;
                        });
                        callback(err,result);
                    })
                },
                function(err,results) {
                    if (err) throw err;
                    // each result entry has 3 urls
                }
            );
        }
     )

});

Да, има повече обаждания към базата данни, но наистина са само десет и следователно всъщност не е проблем.

Истинската резолюцията за това е описана в SERVER-9377 - Разширете $push или $max, за да позволите събирането на "топ " N стойности на ключ _id в $group фаза . Това има обещаващия статус „В процес на изпълнение“, така че по него се работи активно.

След като това бъде решено, единичен оператор за агрегиране става жизнеспособен, тъй като тогава ще можете да „ограничите“ получените „url адреси“ в началния $push само до три записа, вместо да премахнете всички освен три след факта.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Изпълнението на Meteor на localhost се проваля с RangeError:портът трябва да е>=​​0 и <65536:NaN

  2. MongoDB - Логическо ИЛИ при търсене на думи и фрази чрез пълнотекстово търсене

  3. MongoDB $tan

  4. Актуализиране на поле на документ в mongo въз основа на стойността на друго поле

  5. Mongodb findAndModify възел js