英文:
How do you include an attribute from a lower level include in an ancestor attribute set?
问题
I have translated the relevant portions of your text as requested. Here is the translated text:
Sequalize(MySQL)熟悉的人有一个问题。 有人知道将嵌套包含中的属性放在上面的属性集中的正确方法吗?
示例Sequelize请求...
```js
const pupils = await sequelize.Pupil.findByPk(1, {
	attributes: ['id','name'],
	include: [
		{
			model: sequelize.PupilGrade,
			as: 'pupilGrades',
			attributes: ['id','pupilId','subjectId','grade'],
			include: [
				{
					model: sequelize.Subject,
					as: 'subject',
					attributes: ['id','name'],
				},
			],
		},
	],
});
结果数组...
[
	{
		"id": 1,
		"name": '学生A',
		"pupilGrades": [
			{
				"id": 1,
				"pupilId": 1,
				"subjectId": 1,
				"grade": 'B+',
				"subject": {
					"id": 1,
					"name": "数学"
				}
			},				
		],
	},
]
期望的数组...
[
	{
		"id": 1,
		"name": '学生A',
		"pupilGrades": [
			{
				"id": 1,
				"pupilId": 1,
				"subject": "数学",
				"grade": 'B+',
			},				
		],
	},
]
我想知道如何在“PupilGrades”的属性集中包含“Subject”的“name”属性。
我尝试过使用Sequelize.col()...
[Sequelize.col('subject.name'), 'subject'],
然而,它认为subject是一个属性而不是一个包含表,并返回:
错误:未知列 'pupil->pupilGrades.subject.name'
在包含级别,我试过以下方法但无法解决:
{
	model: sequelize.PupilGrade,
	as: 'pupilGrades',
	attributes: [
		'id',
		'pupilId',
		'subjectId',
		'grade',
		[Sequelize.col('subject.name'), 'name'],
	],
	include: [
		{
			model: sequelize.Subject,
			as: 'subject',
			attributes: ['id','name'],
		},
	],
},
任何帮助将不胜感激。
根据Emma的建议,我尝试了以下方法。
[Sequelize.literal('`pupilGrades->subject`.name'), 'subject'],
经过进一步测试,似乎Sequelize存在问题。
const pupil = await req.db.Pupil.findByPk(1, {
	logging: console.log,
	attributes: [
		'id',
		'name',
	],
	include: [
		{ 
			model: req.db.PupilGrade,
			as: 'pupilGrades',
			attributes: ['id','pupilId','subjectId','grade',
				[Sequelize.literal('`pupilGrades->subject`.name'), 'subject'],
			],
			include: [
				{
					model: req.db.Subject,
					as: 'subject',
					attributes: [],
				},
			],
		},
	],
});
以上代码生成以下SQL语句:
SELECT 
`Pupil`.`id`,
`Pupil`.`name`, 
`pupilGrades`.`id` AS `pupilGrades.id`,
`pupilGrades`.`pupil_id` AS `pupilGrades.pupilId`,
`pupilGrades`.`subject_id` AS `pupilGrades.subjectId`, 
`pupilGrades`.`grade` AS `pupilGrades.grade`, 
`pupilGrades->subject`.name AS `pupilGrades.subject`
FROM `pupil` AS `Pupil`
LEFT OUTER JOIN `pupil_grade` AS `pupilGrades` ON `Pupil`.`id` = `pupilGrades`.`pupil_id` 
LEFT OUTER JOIN `subject` AS `pupilGrades->subject` ON `pupilGrades`.`subject_id` = `pupilGrades->subject`.`id` 
WHERE `Pupil`.`id` = 1;
返回正确的数据集:
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
| id | name    | pupilGrades.id | pupilGrades.pupilId | pupilGrades.subjectId | pupilGrades.grade | pupilGrades.subject |
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
|  1 | 学生 A  |              1 |                   1 |                     1 | B+                | 数学                |
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
然而,Sequelize返回以下对象,其中pupilGrades.subject列丢失。
{
	"pupil":{
		"id":1,
		"name":"学生 A",
		"pupilGrades":[
			{
				"id":1,
				"pupilId":1,
				"subjectId":1,
				"grade":"B+"
			}
		]
	}
}
<details>
<summary>英文:</summary>
A question for those familiar with Sequalize (MySQL). Does anyone know the correct method to place an attribute from a nested include within the attribute set above?
Example Sequelize request...
const pupils = await sequelize.Pupil.findByPk(1, {
attributes: ['id','name'],
include: [
{
model: sequelize.PupilGrade,
as: 'pupilGrades',
attributes: ['id','pupilId','subjectId','grade'],
include: [
{
model: sequelize.Subject,
as: 'subject',
attributes: ['id','name'],
},
],
},
],
});
Resulting array...
[
{
"id": 1,
"name": 'Pupil A',
"pupilGrades": [
{
"id": 1,
"pupilId": 1,
"subjectId": 1,
"grade": 'B+',
"subject": {
"id": 1,
"name": "Math"
}
},
],
},
]
Desired array...
[
{
"id": 1,
"name": 'Pupil A',
"pupilGrades": [
{
"id": 1,
"pupilId": 1,
"subject": "Math",
"grade": 'B+',
},
],
},
]
I would like to know how to include the 'name' attribute from 'Subject' within the attribute set of 'PupilGrades'. 
I have tried using Sequelize.col()...
[Sequelize.col('subject.name'), 'subject'],
However, it thinks subject is a attribute not an include table and returns:
Error: Unknown column 'pupil->pupilGrades.subject.name'
I am struggling to figure out how to achieve this at the include level having tried the following:
    {
        model: sequelize.PupilGrade,
        as: 'pupilGrades',
        attributes: [
			'id',
			'pupilId',
			'subjectId',
			'grade',
			[Sequelize.col('subject.name'), 'name'],
		],
        include: [
            {
                model: sequelize.Subject,
                as: 'subject',
                attributes: ['id','name'],
            },
        ],
    },
Any help much appreciated.
I have tried the following as per Emma's suggestion.
[Sequelize.literal('pupilGrades->subject.name'), 'subject'],
After further tests it looks like there is an issue with Sequelize.
const pupil = await req.db.Pupil.findByPk(1, {
logging: console.log,
attributes: [
'id',
'name',
],
include: [
{
model: req.db.PupilGrade,
as: 'pupilGrades',
attributes: ['id','pupilId','subjectId','grade',
[Sequelize.literal('pupilGrades->subject.name'), 'subject'],
],
include: [
{
model: req.db.Subject,
as: 'subject',
attributes: [],
},
],
},
],
});
The code above generates the following SQL statement:
SELECT
Pupil.id,
Pupil.name,
pupilGrades.id AS pupilGrades.id,
pupilGrades.pupil_id AS pupilGrades.pupilId,
pupilGrades.subject_id AS pupilGrades.subjectId,
pupilGrades.grade AS pupilGrades.grade,
pupilGrades->subject.name AS pupilGrades.subject
FROM pupil AS Pupil
LEFT OUTER JOIN pupil_grade AS pupilGrades ON Pupil.id = pupilGrades.pupil_id
LEFT OUTER JOIN subject AS pupilGrades->subject ON pupilGrades.subject_id = pupilGrades->subject.id
WHERE Pupil.id = 1;
Returning the correct dataset:
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
| id | name    | pupilGrades.id | pupilGrades.pupilId | pupilGrades.subjectId | pupilGrades.grade | pupilGrades.subject |
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
|  1 | Pupil A |              1 |                   1 |                     1 | B+                | Math                |
+----+---------+----------------+---------------------+-----------------------+-------------------+---------------------+
However, Sequelize returns the following object with the pupilGrades.subject column missing.
{
"pupil":{
"id":1,
"name":"Pupil A",
"pupilGrades":[
{
"id":1,
"pupilId":1,
"subjectId":1,
"grade":"B+"
}
]
}
}
</details>
# 答案1
**得分**: 0
我不知道为什么你的`Sequelize.col`语法不起作用,但你可以尝试这样做。`Sequelize.col`应该正确地转义别名,但在你的情况下似乎没有。如果我找到了解决方法,我会更新这个答案。
据我所知,在将`Sequelize.col`添加到模型别名(`pupilGrades`)的情况下它不起作用。如果我将`Sequelize.col`添加到顶级,我就看不到任何问题。
```javascript
{
    model: sequelize.PupilGrade,
    as: 'pupilGrades',
    attributes: [
        'id',
        'pupilId',
        'grade',
        [Sequelize.literal('`pupilGrades->subject`.name'), 'subject_name'],
    ],
    include: [
        {
            model: sequelize.Subject,
            as: 'subject',
            attributes: [],  // 不需要嵌套子对象
        },
    ],
}
请注意,我不能在关联模型和同一查询中的属性中使用相同的别名。
英文:
I don't know why your syntax with Sequelize.col doesn't work but you can try this. Sequelize.col supposed to escape the aliases correctly, however, it didn't in your case. If I find something, I will update this answer.
AFAIK, it doesn't work when I add Sequelize.col to where a model is aliased (pupilGrades). If I add Sequelize.col to top level, I don't see any problems.
{
    model: sequelize.PupilGrade,
    as: 'pupilGrades',
    attributes: [
        'id',
        'pupilId',
        'grade',
        [Sequelize.literal('`pupilGrades->subject`.name'), 'subject_name'],
    ],
    include: [
        {
            model: sequelize.Subject,
            as: 'subject',
            attributes: [],  // Do not need sub nested object
        },
    ],
},
** Note that I cannot use the same alias name in associated model and attributes in same query.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论