gpt4 book ai didi

mysql - 在 Eager Loading 中计算 AVG 时,Sequelize 返回一个结果

转载 作者:行者123 更新时间:2023-12-03 22:30:08 25 4
gpt4 key购买 nike

我一直试图解决这个问题一天,但没有运气。我正在使用带有 Nodejs 和 MySQL 方言的 Sequelize。
我正在查询影响者,同时还从影响者评级记录中计算他们的平均评级。它们通过 oneToMany 关系关联。
这是我的影响者模式:

const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('influencer', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
display_name: {
type: DataTypes.STRING(255),
allowNull: false
},
link_facebook: {
type: DataTypes.STRING(255),
allowNull: true
},
link_soundcloud: {
type: DataTypes.STRING(255),
allowNull: true
},
link_twitter: {
type: DataTypes.STRING(255),
allowNull: true
},
link_bandcamp: {
type: DataTypes.STRING(255),
allowNull: true
},
link_spotify: {
type: DataTypes.STRING(255),
allowNull: true
},
link_instagram: {
type: DataTypes.STRING(255),
allowNull: true
},
link_deezer: {
type: DataTypes.STRING(255),
allowNull: true
},
link_youtube: {
type: DataTypes.STRING(255),
allowNull: true
},
link_website: {
type: DataTypes.STRING(255),
allowNull: true
},
description_english: {
type: DataTypes.STRING(255),
allowNull: true
},
description_french: {
type: DataTypes.STRING(255),
allowNull: true
},
information_english: {
type: DataTypes.STRING(255),
allowNull: true
},
information_french: {
type: DataTypes.STRING(255),
allowNull: true
},
enabled: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: 0
},
profile_image: {
type: DataTypes.STRING(255),
allowNull: true
},
banner_image: {
type: DataTypes.STRING(255),
allowNull: true
},
admin_public_status: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: 1
}
}, {
sequelize,
tableName: 'influencer',
timestamps: false,
underscored: true,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
]
});
};
这是我的 InfluencerRating 模式:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('influencer_rating', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
description: {
type: DataTypes.STRING(255),
allowNull: false
},
influencer_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'influencer',
key: 'id'
}
},
rating: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
tableName: 'influencer_rating',
timestamps: false,
underscored: true,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
{
name: "type_id",
using: "BTREE",
fields: [
{ name: "influencer_id" },
]
},
]
});
};
这是我两者之间的关联:
influencer_rating.belongsTo(influencer, { as: "influencer", foreignKey: "influencer_id"});
influencer.hasMany(influencer_rating, { as: "influencer_ratings", foreignKey: "influencer_id"});
这是我查找影响者并计算他们的平均评分的查询:
var influencers = await Influencer.findAll(
{
where: {
[db.Op.and]: [
{
enabled: true
},
{
display_name: {
[db.Op.like]: '%' + filter + '%'
}
},
{
admin_public_status: true
}
],
},
include: [
[
{
model: InfluencerRating,
as: "influencer_ratings",
required: false,
attributes: [[Sequelize.fn('AVG', Sequelize.col('rating')), 'rating']]
}
],
limit: 10,
offset: 0,
group: ['id']
}
);

查询应该返回 2 个影响者对象,但我只得到一个。
如果我删除我的,我会得到想要的行为:
attributes: [[Sequelize.fn('AVG', Sequelize.col('rating')), 'rating']]
我曾尝试计算我的 InfluencerRating 之外的平均值,但不是运气。

最佳答案

对 findAll 进行了一些更改。可以试试:

var influencers = await Influencer.findAll({
// whenever hasMany used in include, the main query gets converted to subquery
// if limit + offset is applied
subQuery: false, // <----- instructs not to make a sub query
attributes: {
include: [
[Sequelize.fn('AVG', Sequelize.col('influencer_ratings.rating')), 'total_rating']
],
},
where: {
[db.Op.and]: [
{ enabled: true },
{ display_name: { [db.Op.like]: '%' + filter + '%' } },
{ admin_public_status: true }
],
},
include: [ // removed extra nesting of array
{
model: InfluencerRating,
as: "influencer_ratings",
required: false,
attributes: [],
}
],
limit: 10,
offset: 0,
group: [
'id',
// 'influencer_ratings.influencer_id', // add if sql error occurs
],
order: [ // if needed
[Sequelize.literal('total_rating'), 'DESC'],
]
});
几个引用链接:
  • 当包含 hasMany/belongsToMany 关系时禁用子查询生成(由 sequelize 完成) - https://github.com/sequelize/sequelize/issues/1756#issuecomment-54748245
  • 使用 SQL 子查询进行排序:https://sequelize.org/master/manual/sub-queries.html

  • 替代方法:
    var influencers = await Influencer.findAll({
    attributes: {
    include: [
    [Sequelize.literal(`(
    SELECT
    AVG("influencer_ratings"."rating") AS "avg_rating"
    FROM
    "influencer" AS "influencer1"
    LEFT OUTER JOIN (
    "influencer_ratings" AS "influencer_ratings"
    ) ON "influencer1"."id" = "influencer_ratings"."influencer_id"
    WHERE
    "influencer1"."id" = "influencer"."id"
    GROUP BY
    "influencer1"."id"
    )`), 'avg_rating'], // now this is just a subquery and will not interfere with other includes
    ],
    },
    where: {
    [db.Op.and]: [
    { enabled: true },
    { display_name: { [db.Op.like]: '%' + filter + '%' } },
    { admin_public_status: true }
    ],
    },
    include: [ // removed extra nesting of array
    // influencer_ratings include not needed now
    // add other includes as needed
    ],
    limit: 10,
    offset: 0,
    order: [ // if needed
    [Sequelize.literal('avg_rating'), 'DESC'],
    ]
    });

    关于mysql - 在 Eager Loading 中计算 AVG 时,Sequelize 返回一个结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67774307/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com