MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Zapytanie Mongo do sortowania według odrębnej liczby

To naprawdę (nadal) najlepiej radzą sobie z wieloma zapytaniami, ponieważ MongoDB naprawdę „nadal” nie ma naprawdę wydajnych operatorów, aby to zrobić.

Możesz zrobić coś takiego z MongoDB 3.2, ale są oczywiste "haczyki":

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] }
    }}
])

A oczywistym problemem jest to, że bez względu na wszystko, nadal dodajesz wszystkie zawartości „url” do zgrupowanej tablicy. Może to potencjalnie przekroczyć limit BSON wynoszący 16 MB. Może nie, ale wciąż trochę marnotrawstwem jest dodawanie „wszystkich” treści, gdy chcesz tylko „trzech”.

Więc nawet wtedy prawdopodobnie bardziej praktyczne jest po prostu zapytanie o „adresy URL” osobno w każdym z 10 najlepszych wyników.

Oto lista dla node.js, która pokazuje:

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
                }
            );
        }
     )

});

Tak, to więcej połączeń do bazy danych, ale tak naprawdę jest to tylko dziesięć i dlatego tak naprawdę nie stanowi problemu.

Prawdziwe Rozwiązanie tego problemu jest opisane w SERVER-9377 - Rozszerz $push lub $max, aby umożliwić zbieranie N wartości na klucz _id w fazie $group . Ma on obiecujący status „W toku”, więc aktywnie nad nim pracujemy.

Po rozwiązaniu tego problemu pojedyncza instrukcja agregacji staje się realna, ponieważ wtedy można „ograniczyć” wynikowe „adresy URL” w początkowym $push do tylko trzech wpisów, zamiast usuwać wszystkie oprócz trzech po fakcie.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Nie można znaleźć „IdentityContext” (brakuje dyrektywy using lub odwołania do zestawu)

  2. Słownik upsert w MongoDb

  3. Projektowanie tabel MongoDB i wydajność zapytań

  4. MongoDB oblicza wartości z dwóch tablic, sortowania i ograniczania

  5. Dlaczego otrzymuję pymongo.cursor.Cursor, gdy próbuję wysłać zapytanie do bazy danych mongodb za pośrednictwem pymongo?