Пн goose агрегат, чтобы получить Средний рейтинг, подсчитать каждый рейтинг и вернуть фактические рейтинги - PullRequest
4 голосов
/ 27 февраля 2020

Я пытаюсь получить среднюю оценку для продукта, плюс счет каждой оценки, а также вернуть фактические оценки и использовать нумерацию страниц, чтобы ограничить сумму, которая возвращается, не влияя на среднее значение или количество.

Так что я пытаюсь добиться чего-то вроде этого:

это моя коллекция оценок:

       {
            "productId": "3"
            "userid" : 5,
            "rating" : 5
            "comment": "this is nice"
        },
        {
            "productId": "3"
            "userid" : 2,
            "rating" :4
            "comment": "this is very nice"
        }

и это конечный результат, который я хочу

{
    "_id" : 1,
    "avgRating": "3.6"
    "counts" : [
        {
            "rating" : 5,
            "count" : 8
        },
        {
            "rating" : 3,
            "count" : 2
        },
        {
            "rating" : 4,
            "count" : 4
        },
        {
            "rating" : 1,
            "count" : 4
        }
    ],
   "ratings": [
       {
            "productId": "3"
            "userid" : 5,
            "rating" : 5
            "comment": "this is nice"
        },
        {
            "productId": "3"
            "userid" : 2,
            "rating" :4
            "comment": "this is very nice"
        },
        {
            "productId": "3"
            "userid" : 12,
            "rating" : 4
            "comment": "this is okay"
        }
    ]
}

Пока у меня есть это, что дает мне счет для каждого рейтинга:

db.votes.aggregate([
    { $match: { postId: {$in: [1,2]} } },
    {
      $group: { _id: { post: "$postId", rating: "$vote" }, count: { $sum: 1 } }
    },
    {
      $group: {
        _id: "$_id.post",
        counts: { $push: { rating: "$_id.rating", count: "$count" } }
      }
    }
  ])

1 Ответ

5 голосов
/ 27 февраля 2020

Вы не за горами, нам просто нужно отрегулировать некоторые вещи:

db.votes.aggregate([
    {
        $match:
            {
                postId: {$in: [1, 2]}
            }
    },
    {
        $group: {
            _id: {post: "$postId", rating: "$vote"},
            count: {$sum: 1},
            reviews: {$push : "$$ROOT" } //keep the original document
        }
    },
    {
        $group: {
            _id: "$_id.post",
            counts: {$push: {rating: "$_id.rating", count: "$count"}},
            reviews: {$push: "$reviews"},
            totalItemCount: {$sum: "$count"}, //for avg calculation
            totalRating: {$sum: "$_id.rating"} // //for avg calculation
        }
    },
    {
        $project: {
            _id: "$_id",
            avgRating: {$divide: ["$totalRating", "$totalItemCount"]},
            counts: "$counts",
            reviews: {
                $slice: [
                    {
                        $reduce: {
                            input: "$reviews",
                            initialValue: [],
                            in: { $concatArrays: ["$$value", "$$this"] }
                        }
                    },
                    0, //skip
                    10 //limit
                ]
            }

        }
    }
])

Обратите внимание, что я сохранил текущую структуру конвейера для ясности, однако я чувствую, что использую конвейер, который использует $ facet может быть более эффективным, так как нам не нужно хранить всю коллекцию в памяти при группировании. мы разделим его на два, один текущий конвейер минус раздел обзора, а другой только с $skip и $limit этапами.

РЕДАКТИРОВАТЬ: $ facet version:

db.votes.aggregate([
    {
        "$match": {
            "postId": {"$in": [1, 2]}
        }
    },
    {
        "$facet": {
            "numbers": [
                {
                    "$group": {
                        "_id": {
                            "post": "$postId",
                            "rating": "$vote"
                        },
                        "count": {
                            "$sum": 1.0
                        }
                    }
                },
                {
                    "$group": {
                        "_id": "$_id.post",
                        "counts": {
                            "$push": {
                                "rating": "$_id.rating",
                                "count": "$count"
                            }
                        },
                        "totalItemCount": {
                            "$sum": "$count"
                        },
                        "totalRating": {
                            "$sum": "$_id.rating"
                        }
                    }
                }
            ],
            "reviews": [
                {
                    "$skip": 0.0
                },
                {
                    "$limit": 10.0
                }
            ]
        }
    },
    {
        "$unwind": "$numbers"
    },
    {
        "$project": {
            "_id": "$numbers._id",
            "reviews": "$reviews",
            "avgRating": {"$divide": ["$numbers.totalRating", "$numbers.totalItemCount"]},
            "counts": "$numbers.counts"
        }
    }
]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...