按关联模型排序时,Sequelize 抛出错误“无法找到模型 x 的有效关联”

Posted

技术标签:

【中文标题】按关联模型排序时,Sequelize 抛出错误“无法找到模型 x 的有效关联”【英文标题】:Sequelize throws Error "Unable to find a valid association for model x" When Ordering By Associated Model 【发布时间】:2018-07-16 07:55:40 【问题描述】:

我的sequelize有问题,当我想按关联模型排序查询结果时,sequelize会抛出这个错误:

UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:1):错误:无法找到模型“productLanguage”的有效关联

这些是我的文件:

**Context.js **

const Sequelize = require('sequelize');
const sequelize = new Sequelize("postgres://postgres:123456@localhost:5432/sampleDB");

module.exports = 
    Sequelize: Sequelize,
    sequelize: sequelize

User.js

const context = require('../context');

module.exports = context.sequelize.define('user', 
    name: context.Sequelize.STRING,
    ,
    freezeTableName: true
);

Product.js

const context = require('../context');

module.exports = context.sequelize.define('product', 
    slug: context.Sequelize.STRING,
    price: context.Sequelize.DECIMAL(10,2),
    ,
    freezeTableName: true
);

ProductLanguage.js

const context = require('../context');

module.exports = context.sequelize.define('productLanguage', 
    name: context.Sequelize.STRING,
    ,
    freezeTableName: true,
    timestamps: false
);

Language.js

const context = require('../context');

module.exports = context.sequelize.define('language', 
    name: context.Sequelize.STRING,
    slug: context.Sequelize.STRING,
    ,
    freezeTableName: true
);

db.js

var context = require('./context');
var User = require('./models/User'),
    Product = require('./models/Product'),
    ProductLanguage = require('./models/ProductLanguage'),
    Language = require('./models/Language');


// ===================== ASSOCIATIONS =====================
// user 1:m Product
Product.belongsTo(User); // product owner
User.hasMany(Product);

// Product 1:m ProductLanguage m:1 Language
ProductLanguage.belongsTo(Product);
Product.hasMany(ProductLanguage);
ProductLanguage.belongsTo(Language);
Language.hasMany(ProductLanguage);

module.exports = 
    Sequelize: context.Sequelize,
    sequelize: context.sequelize,
    models: 
        Product: Product,
        User: User,
        ProductLanguage: ProductLanguage,
        Language: Language
    

最后这是我的查询

app.get('/', async (req, res, next)=>

    var result = await db.models.User.findAll(
        include:[
            
                model: db.models.Product,
                attributes: ['price'],
                include: [
                    
                        model: db.models.ProductLanguage,
                        attributes: ['name'],
                        include: [
                            
                                model: db.models.Language, 
                                attributes: ['name'],                               
                            
                        ]
                    
                ]
            
        ],
        order:[
            [db.models.ProductLanguage, 'name', 'desc']
        ],
        attributes: ['name']
    );

    res.send(result);
);

没有“订单”部分的查询工作正常,所以我认为问题应该出在这些:

    这部分有问题:[db.models.ProductLanguage, 'name', 'desc'] 关联定义有问题

注意:我在 youtube 和 *** 和 sequelize 文档上搜索了 4 天,但没有找到。

我使用这些依赖项:

"express": "^4.16.2",
"pg": "^6.4.2",
"pg-hstore": "^2.3.2",
"sequelize": "^4.32.2"

【问题讨论】:

【参考方案1】:

那些仍然无法得到结果的人,试试这个语法 -

order:[[ model: db.models.ProductLanguage, as: 'language_of_product'  , 'name', 'desc']]

【讨论】:

确实,如果在包含中指定了别名,则它也需要存在于订单的模型中。谢谢!【参考方案2】:

除了莫拉多夫的回答,重要的是要注意,如果您为包含的模型指定别名,那么您还必须在 order 语句中指定别名。

在前面的例子的基础上,我们得到:

var result = await db.models.User.findAll(
    include:[
        
            model: db.models.Product,
            as: 'include1',
            attributes: ['price'],
            include: [
                
                    model: db.models.ProductLanguage,
                    as: 'include2',
                    attributes: ['name'],
                    include: [
                        
                            model: db.models.Language, 
                            attributes: ['name'],                               
                        
                    ]
                
            ]
        
    ],
    order:[
        [ model: db.models.Product, as: 'include1' , 
          model: db.sequelize.models.ProductLanguage, as: 'include2' ,
         'name',
         'desc']
    ],
    attributes: ['name']
);

请注意,因为我在 include 语句中将 Product 命名为 include1,所以我还必须在 order 语句中将其命名为 include1

【讨论】:

为什么还需要别名? 在我的项目中有一个别名,我花了一段时间来调试它为什么不起作用。所以我想为别人节省一点时间。【参考方案3】:

我找到了解决办法。

我必须把所有关联的模型整理好,所以正确的查询是:

order:[
        [db.models.Product, db.sequelize.models.ProductLanguage, 'name', 'desc']
    ],

完整的查询必须是:

var result = await db.models.User.findAll(
    include:[
        
            model: db.models.Product,
            attributes: ['price'],
            include: [
                
                    model: db.models.ProductLanguage,
                    attributes: ['name'],
                    include: [
                        
                            model: db.models.Language, 
                            attributes: ['name'],                               
                        
                    ]
                
            ]
        
    ],
    order:[
        [db.models.Product, db.sequelize.models.ProductLanguage, 'name', 'desc']
    ],
    attributes: ['name']
);

我希望这对其他人有所帮助。

【讨论】:

另外,如果您与别名有关联,您也必须指定别名,例如:order:[[db.models.Product, model: db.models.ProductLanguage, as: 'language_of_product' , 'name', 'desc']] 关于上面的例子:如果你使用别名,你不需要在对象之前提到模型所以查询变成 - order:[[ model: db.models.ProductLanguage, as : 'language_of_product' , 'name', 'desc']]

以上是关于按关联模型排序时,Sequelize 抛出错误“无法找到模型 x 的有效关联”的主要内容,如果未能解决你的问题,请参考以下文章

Sequelize - 如何提取具有 1 个关联记录的记录并按关联记录属性排序

Sequelize:在关联中排序

Sequelize model.sync() 抛出错误

Sequelize - 在验证模型的关联时获取正确的路径

在 sequelize v6 中包含模型的问题排序 [已解决] - 这不是 sequelize 错误

Sequelize:急切加载和排序(在父表上)