如何正确映射sequelize.js中关系的属性?
我正在创建一个食谱数据库(通常称为烹饪书),在这里,我需要在配料和食谱之间建立多对多的关系,并且我正在结合使用 当一种成分被添加到配方中时,我需要声明进入配方的该成分的正确数量 我已声明(简化示例) 我的问题是,当我的一个REST端点返回数据时,数据是如何返回的如何正确映射sequelize.js中关系的属性?,sequelize.js,postgresql,javascript,node.js,Sequelize.js,Postgresql,Javascript,Node.js,我正在创建一个食谱数据库(通常称为烹饪书),在这里,我需要在配料和食谱之间建立多对多的关系,并且我正在结合使用 当一种成分被添加到配方中时,我需要声明进入配方的该成分的正确数量 我已声明(简化示例) 我的问题是,当我的一个REST端点返回数据时,数据是如何返回的 router.get('/recipes', function(req, res) { Recipe.findAll({ include: [{ model: Ingredient,
router.get('/recipes', function(req, res) {
Recipe.findAll({
include: [{
model: Ingredient,
as: 'ingredients'
}]
}).then(function(r) {
return res.status(200).json(r[0].toJSON());
})
});
发送到客户端的结果JSON如下所示(省略时间戳):
而我想要的只是
{
"id": 1,
"name": "Carrots",
"ingredients": [
{
"id": 1,
"name": "carrot",
"amount": 12,
}
]
}
也就是说,我希望关系表中的amount
字段包含在结果中,而不是整个RecipeCredit
对象中
sequelize生成的数据库如下所示:
Ingredients
id name
1 carrot
Recipes
id name
1 Carrots
RecipeIngredients
amount RecipeId IngredientId
12 1 1
include: [{
model: Ingredient,
as: 'ingredients',
attributes: []
}]
router.get('/recipes', function(req, res) {
Recipe.findAll({
include: [{
model: Ingredient,
as: 'ingredients',
through: {
attributes: ['amount']
}
}]
}).then(function(recipes) {
return recipes[0].toJSON();
}).then(function(recipe) {
recipe.ingredients = recipe.ingredients.map(function(i) {
i.amount = i.RecipeIngredient.amount;
delete i.RecipeIngredient;
return i;
});
return recipe;
}).then(function(recipe) {
return res.status(200).json(recipe);
});
});
但是将['amount']
或['RecipeCredit.amount']
设置为属性值会引发如下错误
未处理的拒绝SequelizeDatabaseError:列Components.RecipeInCredit.amount不存在
显然,我可以在JS中使用
.map
修复这个问题,但肯定有办法让sequelize为我完成这项工作 我查看了文档,但找不到任何可以让我将联接表的属性合并到结果中的内容,因此看起来我不得不这样做:
Ingredients
id name
1 carrot
Recipes
id name
1 Carrots
RecipeIngredients
amount RecipeId IngredientId
12 1 1
include: [{
model: Ingredient,
as: 'ingredients',
attributes: []
}]
router.get('/recipes', function(req, res) {
Recipe.findAll({
include: [{
model: Ingredient,
as: 'ingredients',
through: {
attributes: ['amount']
}
}]
}).then(function(recipes) {
return recipes[0].toJSON();
}).then(function(recipe) {
recipe.ingredients = recipe.ingredients.map(function(i) {
i.amount = i.RecipeIngredient.amount;
delete i.RecipeIngredient;
return i;
});
return recipe;
}).then(function(recipe) {
return res.status(200).json(recipe);
});
});
通过将传递到包含
可以从联接表中筛选出要包含的属性,但在我的一生中,我找不到让sequelize为我合并它的方法
上面的代码将返回我想要的输出,但是增加了循环成分列表的开销,这不是我想要的,但是除非有人提出更好的解决方案,否则我看不到其他方法来实现这一点。您可以使用sequelize.literal。使用配方的配料别名,您可以编写如下内容。我不知道这是不是正确的方法
我使用sqlite3进行了测试。收到的别名为“ir”的结果为
请参阅此处的完整代码
这一次我已经晚了很多,但是我看到它被浏览了很多次,所以这里是我关于如何合并的答案
属性
这本书中有一些随机的例子
router.get('/recipes', function(req, res) {
Recipe.findAll({
include: [{
model: Ingredient,
as: 'ingredients',
through: {
attributes: ['amount']
}
}]
})
.then(docs =>{
const response = {
Deal: docs.map(doc =>{
return{
cakeRecipe:doc.recipe1,
CokkieRecipe:doc.recipe2,
Apples:doc.ingredients.recipe1ingredient
spices:[
{
sugar:doc.ingredients.spice1,
salt:doc.ingredients.spice2
}
]
}
})
}
})
res.status(200).json(response)
})
router.get('/recipes', function(req, res) {
Recipe.findAll({
include: [{
model: Ingredient,
as: 'ingredients',
through: {
attributes: ['amount']
}
}]
})
.then(docs =>{
const response = {
Deal: docs.map(doc =>{
return{
cakeRecipe:doc.recipe1,
CokkieRecipe:doc.recipe2,
Apples:doc.ingredients.recipe1ingredient
spices:[
{
sugar:doc.ingredients.spice1,
salt:doc.ingredients.spice2
}
]
}
})
}
})
res.status(200).json(response)