Toto je skutečně (stále) nejlépe řešeno více dotazy, protože MongoDB skutečně "stále" nemá skutečně efektivní operátory, aby to udělali.
Něco takového však můžete udělat s MongoDB 3.2, ale jsou zde zřejmé „úlovky“:
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 zřejmý problém je, že ať se děje cokoliv, stále přidáváte vše obsahu "url" do seskupeného pole. To má potenciál překročit limit BSON 16 MB. Možná ne, ale stále je trochu zbytečné přidávat „veškerý“ obsah, když chcete pouze „tři“.
Takže i tak je pravděpodobně praktičtější dotazovat se na „url“ samostatně u každého z 10 nejlepších výsledků.
Zde je výpis node.js, který ukazuje:
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
}
);
}
)
});
Ano, je to více volání do databáze, ale ve skutečnosti je to jen deset a proto ve skutečnosti není problém.
skutečný rozlišení je zahrnuto v SERVER-9377 – Rozšiřte $push nebo $max, abyste mohli sbírat „top“ " N hodnot na klíč _id ve fázi $group . Toto má slibný status „In Progress“, takže se na něm aktivně pracuje.
Jakmile se to vyřeší, stane se životaschopným jediný agregační příkaz, od té doby byste mohli „omezit“ výsledné „url“ v počátečním $push
na pouhé tři položky, než aby poté všechny kromě tří odstranili.