Sequelize v5-通过嵌套包含分组

时间:2019-11-17 23:15:31

标签: postgresql optimization group-by orm sequelize.js

我要优化的查询使用下表:

DSD of the database

我当前的(工作但未优化的)查询在“锻炼”模型(存储为范围)中看起来像这样

    exercise_with_metrics_and_tags_and_categories_related(ids) {
        return {
            // no need for that part here
            attributes: [
                "id",
                "title",
                "description",
                "version",
                "createdAt",
                "updatedAt"
            ],
            where: {
                id: {
                    [Op.in]: ids
                }
            },

            include: [
                // load exercise evaluation
                {
                    model: sequelize.models.Exercise_Metrics,
                    as: "metrics",
                    required: true,
                    attributes: [
                        ["vote_count", "votes"],
                        ["avg_vote_score", "avg_vote"]
                    ]
                },
                // load tags linked to this exercise ( with their category included )
                // required : true for inner join (by default, it uses left outer join which is bad )
                {
                    model: sequelize.models.Tag,
                    as: "tags",
                    required: true,
                    // credits to Stackoverflow : https://stackoverflow.com/a/45093383/6149867
                    through: {attributes: []}, //<-- this line will prevent mapping object from being added
                    attributes: [
                        ["id", "tag_id"],
                        ["text", "tag_text"]
                    ],
                    include: [
                        {
                            model: sequelize.models.Tag_Category,
                            as: "category",
                            required: true,
                            attributes: [
                                ["id", "category_id"],
                                ["kind", "category_text"]
                            ]
                        }
                    ]
                }
            ]
        }
    }

我用调用的:

    const ids = [/*Some ids I got from other query*/];
    models
        .Exercise
        .scope({
            method: ["exercise_with_metrics_and_tags_and_categories_related", ids]
        })
        .findAll()

哪个给了我以下sql查询:

SELECT "Exercise"."id",
       "Exercise"."title",
       "Exercise"."description",
       "Exercise"."version",
       "Exercise"."createdAt",
       "Exercise"."updatedAt",
       "metrics"."id" AS "metrics.id",
       "metrics"."vote_count" AS "metrics.votes",
       "metrics"."avg_vote_score" AS "metrics.avg_vote",
       "tags"."id" AS "tags.id",
       "tags"."id" AS "tags.tag_id",
       "tags"."text" AS "tags.tag_text",
       "tags->Exercise_Tag"."exercise_id" AS "tags.Exercise_Tag.exercise_id",
       "tags->Exercise_Tag"."tag_id" AS "tags.Exercise_Tag.tag_id",
       "tags->category"."id" AS "tags.category.id",
       "tags->category"."id" AS "tags.category.category_id",
       "tags->category"."kind" AS "tags.category.category_text"
FROM "exercises_library"."Exercises" AS "Exercise"
INNER JOIN "exercises_library"."Exercises_Metrics" AS "metrics" ON "Exercise"."id" = "metrics"."exercise_id"
INNER JOIN ("exercises_library"."Exercises_Tags" AS "tags->Exercise_Tag"
            INNER JOIN "exercises_library"."Tags" AS "tags" ON "tags"."id" = "tags->Exercise_Tag"."tag_id") ON "Exercise"."id" = "tags->Exercise_Tag"."exercise_id"
INNER JOIN "exercises_library"."Tag_Categories" AS "tags->category" ON "tags"."category_id" = "tags->category"."id"
WHERE "Exercise"."id" IN (2,
                          3);

如果联接“ Exercise-Exercise_Metrics”的联接可以忽略不计(它是1:1的多重性),则其余查询则不然。我希望Sequelize在加入Exercise(和Exercise_Metrics)之前,对嵌套关联(Exercise_Tags,Tag,Tag,Tag_Category)进行聚合。

我知道Postgresql具有生成json聚合的功能:

  • json_agg
  • json_build_object
  • array_to_json

您将如何做?预先谢谢你

PS:请不要建议使用参数化的原始查询:我很好奇,看看是否有可能以适当的方式在Sequelize中做到这一点;)

我的配置:

续集v5 PostgreSQL 12

0 个答案:

没有答案