javascript - 续集 findOne/findAll 查询不返回关联属性
问题描述
我正在尝试使用 Sequelize 获得一个基本的关联/连接查询,但似乎无法从包含关联中获取数据。到目前为止,我尝试了多种方法均无济于事,但目前正在使用以下方法(为演示而简化):
// package.json
{
...
"dependencies": {
"pg": "^7.18.1",
"pg-hstore": "^2.3.3",
"sequelize": "^5.21.4"
}
}
// sequelize.js
const Sequelize = require('sequelize')
const options = {
...
databaseVersion: '8.0.2', // RedShift Postgres version
dialect: 'postgres',
dialectOptions: {
ssl: {
require: true,
rejectUnauthorized: true
}
}
define: {
timestamps: false,
freezeTableName: true
}
}
const sequelize = new Sequelize(<database>, <user>, <pass>, options)
module.exports = sequelize
// modelA.model.js
const { DataTypes } = require('sequelize')
const sequelize = require('./sequelize')
const schema = 'my_schema'
const tableName = 'my_table_a'
const modelName = 'ModelA'
const attributes = {
model_a_key: {
type: DataTypes.CHAR(32)
},
model_a_value: {
type: DataTypes.STRING
}
model_b_key: {
type: DataTypes.CHAR(32)
},
}
const options = {
schema
tableName
}
sequelize.define(modelName, attributes, options)
// modelB.model.js
const { DataTypes } = require('sequelize')
const sequelize = require('./sequelize')
const schema = 'my_schema'
const tableName = 'my_table_b'
const modelName = 'ModelB'
const attributes = {
model_b_key: {
type: DataTypes.CHAR(32)
},
model_b_value: {
type: DataTypes.STRING
}
}
const options = {
schema
tableName
}
sequelize.define(modelName, attributes, options)
// associations.js
const { models } = require('./sequelize.js')
ModelA.belongsTo(models.ModelB, { foreignKey: 'model_b_key' })
// Have left this out for now since I can't seem to even leverage the above association properly...
// ModelB.belongsTo(models.ModelA, { foreignKey: 'model_b_key' })
上述文件按 sequelize、models、associations 的顺序加载。在我看到的 Sequelize 示例之后,我尝试了以下查询来访问 ModelA 及其关联的 ModelB 的数据:
// Attempt #1
await sequelize.models.ModelA.findOne({ include: ['ModelB'] })
// returned data = { model_a_key, model_a_value, model_b_key }; missing all ModelB columns
// Attempt #2
await sequelize.models.ModelA.findOne({ attributes: ['ModelB.model_b_value'], include: ['ModelB'] })
// returned data = {}
// Attempt #3
await sequelize.models.ModelA.findOne({ include: [{ association: 'ModelB', required: true }] })
// returned data = { model_a_key, model_a_value, model_b_key }; missing all ModelB columns
// Attempt #4
await sequelize.models.ModelA.findOne({ include: [{ association: 'ModelB', attributes: ['model_b_value'] }] })
// returned data = { model_a_key, model_a_value, model_b_key }; missing model_b_value
生成的 SQL 似乎在实际获取感兴趣的列方面进行了检查,例如尝试 #1 产生:
SELECT "ModelA"."model_a_key", "ModelA"."model_a_value", "ModelA"."model_b_key", "ModelB"."model_b_key" AS "ModelB.model_b_key", "ModelB"."model_b_value" AS "ModelB.model_b_value"
FROM "my_schema"."my_table_a" AS "ModelA"
LEFT OUTER JOIN "my_schema"."my_table_b" AS "ModelB" ON "ModelA"."model_b_key" = "ModelB"."model_b_key"
LIMIT 1;
如果我设置选项,这些值也可用raw: true
。但是,如果我尝试使用模型对象,则有关关联 ModelB 的所有信息似乎都会丢失/丢弃 - 返回的对象上既不存在嵌套对象,也不ModelB
存在的属性。ModelB.model_b_key
ModelB.model_b_value
我在这里错过了一些超级简单的东西吗?一直在拼命摆弄关联targetKey
、、sourceKey
值foreignKey
以及更多类似上面列出的 findOne/findAll 查询排列,但运气为零。
任何建议将不胜感激!
更新一
经过一番摆弄之后,在设置关联时似乎存在一些区分大小写的奇怪行为。如果我定义与别名的关联as: 'modelb'
并通过 查询association: 'modelb'
,上面的 fetch 语句按预期工作,并将所需的 ModelB 属性映射到返回的对象上。将任何大写字符引入别名似乎会破坏此功能 - 例如,别名xxxxxx
工作正常,xxxxXx
会导致上述原始问题。
直接的解决方法似乎是只用小写来给所有东西起别名,但我仍然想继续按预期工作。我希望这只是与 Postgres 和我的 Sequelize 配置与实际问题有关。
更新二
所以看起来所有大写的列引用/别名,虽然SELECT "ModelB"."model_b_key" AS "ModelB.model_b_key"
在构造的 SQL 查询中表示为定义(例如),但从客户端返回的行对象属性pg
返回小写(例如row['modelb.model_b_key']
)。结果,字段标签不再与其原始关联标签对齐,并且没有任何数据映射到模型实例。
设置 Sequelize 选项minifyAliases: true
似乎可以解决问题。启用此选项后,列别名在查询中表示为_01
、_02
等,然后映射回它们各自的字符串标签,从而避免别名被无意中转换为小写的可能性。
更新三
如果有人感兴趣,这实际上似乎是 AWS Redshift 特定的行为。我不知道 Redshift 默认将所有列名(和别名)转换为小写(通过describe_field_name_in_uppercase控制),这解释了为什么所有返回的行对象都将其别名转换为小写。""
我想这对于使用双引号列名/别名引用尊重大写/小写的传统 Postgres 实现来说不是问题。
解决方案
意识到我可以发布答案 - 所以如果其他人遇到这个问题,这些是我目前的发现/解决方案:
因此,似乎所有大写的列引用/别名,尽管
SELECT "ModelB"."model_b_key" AS "ModelB.model_b_key"
在构造的 SQL 查询中表示为定义(例如),从 pg 客户端返回的行对象属性都返回小写(例如row['modelb.model_b_key']
)。结果,字段标签不再与其原始关联标签对齐,并且没有任何数据映射到模型实例。设置 Sequelize 选项
minifyAliases: true
似乎可以解决问题。启用此选项后,列别名在查询中表示为_0
、_1
等,然后映射回它们各自的字符串标签,从而避免别名被无意中转换为小写的可能性。这实际上似乎是与 Sequelize/pg 一起出现的 AWS Redshift 特定行为。我不知道 Redshift 默认将所有列名(和别名)转换为小写(通过describe_field_name_in_uppercase控制),这解释了为什么所有返回的行对象都将其别名转换为小写。
""
我想这对于使用双引号列名/别名引用尊重大写/小写的传统 Postgres 实现来说不是问题。
推荐阅读
- asp.net-core-2.0 - Asp.Net Core:如何正确地将数据从视图传递到控制器?
- javascript - 使用 JavaScript 的搜索栏中的词序
- node.js - 如何使用 Material-UI 创建 onSubmit
- apache-kafka - 如何将消息类型绑定到单个消费者组上的 Kafka 消费者?
- rabbitmq - 如果已经存在,RabbitMQ 是否创建队列/交换?
- spring-boot - 结合 oauth2+jwt 配置多个身份验证提供程序
- node.js - 在此示例中,如何使用 docker-compose 允许 2 个容器正确共享 .sock 文件?
- flutter - Flutter ButtonBar 儿童尺寸
- c# - 使用 svcutil 从 xsd 生成 DataContract 的问题
- python - 根据特定键合并字典列表