按类别划分的mongodb聚合组

按类别划分的mongodb聚合组,mongodb,mongoose,mongodb-query,aggregation-framework,mongodb-aggregation,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,Mongodb Aggregation,我不熟悉使用MongoDB的聚合框架,这里我有一个模式: var bookSoldSchema = new Schema({ buyer:{ type: Number } book: { type: Schema.Types.ObjectId, ref: 'Book' } }); var bookSchema = new Schema({ bookName: { type: String }, catego

我不熟悉使用MongoDB的聚合框架,这里我有一个模式:

var bookSoldSchema = new Schema({
   buyer:{
      type: Number
   }
   book: {         
     type: Schema.Types.ObjectId, ref: 'Book'
   } 
});

 var bookSchema = new Schema({
     bookName: { type: String },
     categories: [{ type: Schema.Types.ObjectId, ref: 'BookCategory'}],
 })
每本书都有多个类别,我想展示前5名的畅销书类别,我需要的每一个类别都展示最畅销的前3本书,我还需要展示类别名称,我需要的结果是:

[
      {
        categoryId: xxx,
        categoryName:xxx,
        top3books:[
           {bookId:xxx, bookName:xxx},
           {bookId:xxx, bookName:xxx},
           {bookId:xxx, bookName:xxx},
        ]
     },
     {
       categoryId: xxx,
       categoryName:xxx,
       top3books:[
          {bookId:xxx, bookName:xxx},
          {bookId:xxx, bookName:xxx},
          {bookId:xxx, bookName:xxx},
       ]
    }
]

在MongoDB我该怎么做

您可以运行以下聚合管道,假设您有一个模型
BookSold
,该模型使用上面的
bookSoldSchema
books
bookscategories
基础集合:

BookSold.aggregate([
    {
        "$lookup": {
            "from": "books",
            "localField": "book",
            "foreignField": "_id",
            "as": "book_join"
        }
    },
    { "$unwind": "$book_join" },
    { "$unwind": "$book_join.categories" },
    {
        "$lookup": {
            "from": "bookcategories",
            "localField": "book_join.categories",
            "foreignField": "_id",
            "as": "categories"
        }
    },
    { "$unwind": "$categories" },
    { "$sort": { "categories.name": 1, "buyer": -1 } }, 
    {
        "$group": {
            "_id": "$categories.name",
            "categoryId": { "$first": "$categories._id" },
            "buyer": { "$first": "$buyer" },
            "books": { 
                "$push": { 
                    "bookId": "$book_join._id", 
                    "bookName": "$book_join.bookName" 
                } 
            }
        }
    },
    { "$sort": { "buyer": -1 } },
    { "$limit": 5 },
    {
       "$project": {
           "_id": 0,
           "categoryId": 1,
           "categoryName": "$_id",
           "top3books": { "$slice": [ "$books", 3 ] }
       }
    }
], function(err, result) {
    if (err) handleError(err);
    console.log(JSON.stringify(result, null, 4));
})

您可以运行以下聚合管道,假设您有一个模型
BookSold
,该模型使用上面的
bookSoldSchema
books
bookscategories
基础集合:

BookSold.aggregate([
    {
        "$lookup": {
            "from": "books",
            "localField": "book",
            "foreignField": "_id",
            "as": "book_join"
        }
    },
    { "$unwind": "$book_join" },
    { "$unwind": "$book_join.categories" },
    {
        "$lookup": {
            "from": "bookcategories",
            "localField": "book_join.categories",
            "foreignField": "_id",
            "as": "categories"
        }
    },
    { "$unwind": "$categories" },
    { "$sort": { "categories.name": 1, "buyer": -1 } }, 
    {
        "$group": {
            "_id": "$categories.name",
            "categoryId": { "$first": "$categories._id" },
            "buyer": { "$first": "$buyer" },
            "books": { 
                "$push": { 
                    "bookId": "$book_join._id", 
                    "bookName": "$book_join.bookName" 
                } 
            }
        }
    },
    { "$sort": { "buyer": -1 } },
    { "$limit": 5 },
    {
       "$project": {
           "_id": 0,
           "categoryId": 1,
           "categoryName": "$_id",
           "top3books": { "$slice": [ "$books", 3 ] }
       }
    }
], function(err, result) {
    if (err) handleError(err);
    console.log(JSON.stringify(result, null, 4));
})

你能添加样本文档进行测试吗?你能添加样本文档进行测试吗?非常感谢@chridam,类别的前三名不是前三名,我想获得该类别中销量最高的前三名,这意味着该类别的最高计数(bookId)。你能帮个忙吗?非常感谢@chridam,类别的前三名不是前三名,我想获得该类别中销量最高的前三名,这意味着该类别的最高数量(bookId)。你能帮忙吗?