Агрегированный запрос MongoDB к SpringDataMongoDB

У меня есть совокупный запрос MongoDB ниже, и я хотел бы иметь эквивалентный запрос SpringData Mongodb.

Совокупный запрос MongoDB:

db.response.aggregate(
        // Pipeline
        [
            // Stage 1 : Group by Emotion & Month
            {
                $group: {
                    _id: {
                        emotion: "$emotion",
                        category: "$category"
                    },
                    count: {
                        $sum: 1
                    },
                    point: {
                        $first: '$point'
                    }
                }
            },
            // Stage 2 : Total Points
            {
                $addFields: {
                    "totalPoint": {
                        $multiply: ["$point", "$count"]
                    }
                }
            },
                        // Stage3 : Group By Category - Overall Response Total & totalFeedbacks
            {
                $group: {
                    _id: '$_id.category',
                    totalFeedbacks: {
                        $sum: "$count"
                    },
                    overallResponseTotal: {
                        $sum: "$totalPoint"
                    }
                }
            },
                        // Stage4 - Overall Response Total & totalFeedbacks
            {
                $project: {
                    _id: 1,
                    overallResponseTotal: '$overallResponseTotal',
                    maxTotalFrom: {
                        "$multiply": ["$totalFeedbacks", 3.0]
                    },
                    percent: {
                        "$multiply": [{
                            "$divide": ["$overallResponseTotal", "$maxTotalFrom"]
                        }, 100.0]
                    }
                }
            },
                        // Stage4 - Percentage Monthwise
                {
                    $project: {
                        _id: 1,
                        overallResponseTotal: 1,
                        maxTotalFrom: 1,
                        percent: {
                            "$multiply": [{
                                "$divide": ["$overallResponseTotal", "$maxTotalFrom"]
                            }, 100.0]
                        }
                    }

                }
            ]
);

Я пробовал это эквивалентно в Spring Data, но застрял на этапе 2 о том, как преобразовать «$ addFields» в код Java. Хотя я искал об этом на нескольких сайтах, но не нашел ничего полезного. См. мой эквивалентный код Java для этапа 1.

//Stage 1 -Group By Emotion and Category and return it's count

GroupOperation groupEmotionAndCategory = Aggregation.group("emotion","category").count().as("count").first("point")
                        .as("point");

Aggregation aggregation = Aggregation.newAggregation(groupEmotionAndCategory);

AggregationResults<CategoryWiseEmotion> output = mongoTemplate.aggregate(aggregation, Response.class, CategoryWiseEmotion.class);

Любая помощь будет высоко оценена.


person Beginner    schedule 05.12.2017    source источник


Ответы (1)


$addFields еще не поддерживается Spring Data Mongodb.

Одним из обходных путей является передача необработанного конвейера агрегации в Spring.

Но поскольку у вас есть ограниченное количество полей после этапа 1, вы также можете понизить этап 2 до проекция:

{
    $project: {
        // _id is included by default
        "count" : 1, // include count
        "point" : 1, // include point
        "totalPoint": {
            $multiply: ["$point", "$count"] // compute totalPoint
        }
    }
}

Я сам не проверял, но эта проекция должна выглядеть примерно так:

ProjectionOperation p = project("count", "point").and("point").multiply(Fields.field("count")).as("totalPoint");

Затем можно аналогичным образом транслировать стадии 3, 4 и 5 и передать весь пайплайн на Aggregation.aggregate().

person Marc Tarin    schedule 05.12.2017
comment
Спасибо @Marc Tarin, это сработало! Но теперь я застрял на этапе 4, чтобы умножить и разделить. Не могли бы вы мне помочь. - person Beginner; 05.12.2017
comment
Проверьте этот поток и попробуйте с project(...).andExpression("overallResponseTotal / maxTotalFrom * 100.0").as("percent"). - person Marc Tarin; 05.12.2017
comment
Марк Тарин , Для // Stage3 : Группировать по категориям - Общий ответ Всего и общее количество отзывов. Я написал это на Java GroupOperation groupCategoryOverAllResponseAndTotalFeedback = Aggregation.group("_id.category").sum("count") .as("totalFeedbacks").sum("totalPoint").as("overallResponseTotal");. Но это дает мне ошибку как неверную ссылку _id.category - person Beginner; 06.12.2017
comment
Я не знаю причин этого, но среда агрегации Spring не принимает _id в качестве допустимого имени поля для определенных этапов агрегации. Вам придется немного повозиться, чтобы найти обходной путь, например, категорию проекта на этапе 2 и обратиться к ней на этапе 3. Помните, что у вас все еще есть возможность передать необработанную агрегацию в Spring. Это помогает ускорить разработку, а затем вы можете вернуться к нему позже, когда вы лучше ознакомитесь с правилами агрегации Spring. - person Marc Tarin; 06.12.2017