Arc*_*Arc 1 javascript sql knex.js
目前我正在使用 Knex 查询 MSSQL 数据库。我有一张这样的表:
MealsId
VegetablesId
Meal (参考膳食表)
FruitsId
Meal (参考膳食表)
因此,一餐 ID 可以包含多种蔬菜或水果。我希望得到一个包含所有蔬菜数组和结果中所有水果数组的膳食 ID 的结果。现在使用knex('meals').innerJoin('fruits', 'meals.id', 'fruits.meal'),我得到了多个对象。
是的,您肯定会通过该查询获得多个对象。您没有指定什么 to SELECT,因此数据库返回所有内容。
对于(我假设)您要实现的目标,整体架构可能不正确。似乎您想要类似这样的输出?
{
Id: 1,
Name: 'Spinach Pie',
Ingredients: [
{ Id: 1, Name: 'Spinach', Type: 'Vegetable' },
{ Id: 2, Name: 'Garlic', Type: 'Vegetable' }
]
}
Run Code Online (Sandbox Code Playgroud)
在您当前的模式下,每种蔬菜或水果只能搭配一顿饭。这是一种 HAS ONE 关系:“一种蔬菜吃一顿饭”。显然,我们可以在各种不同的菜肴中使用任何给定的蔬菜,因此我们需要以不同的方式思考问题。正确的思考方式是,一种蔬菜有很多餐,一顿有很多蔬菜。这将我们引向一个带有连接表的结构:
Meals
- Id
- Name
Ingredients
- Id
- Name
- Type
MealsIngredients
- Id
- Meal
- Ingredient
Run Code Online (Sandbox Code Playgroud)
(我不一定会这样写一本真正的食谱书,但出于演示目的......)
这会给我们一个这样的查询:
knex('Meals')
.select('Meals.Name as mealName', 'Ingredients.*')
.innerJoin('MealsIngredients', 'Meals.Id', 'MealsIngredients.Meal')
.innerJoin('Ingredients', 'Ingredients.Id', 'MealsIngredients.Ingredient')
.where('Meals.Id', mealId)
Run Code Online (Sandbox Code Playgroud)
它不会让你到达你想要的地方,但到目前为止:
[
{ mealName: 'Spinach Pie', Id: 1, Name: 'Spinach', Type: 'Vegetable' },
{ mealName: 'Spinach Pie', Id: 2, Name: 'Garlic', Type: 'Vegetable' }
]
Run Code Online (Sandbox Code Playgroud)
要将其与餐点的详细信息结合起来,有多种选择。我们可以发出两个单独的查询,或某种数组聚合(我不太熟悉 SQL Server 在那里的选项)。鉴于这里的要求相对简单,您可能只需在 JS 中组装您想要的对象:
const outputFormatter = (output, ingredient) => {
output.name = ingredient.mealName
if (!output.ingredients) {
output.ingredients = []
}
const { mealName, ...theIngredient } = ingredient
output.ingredients.push(...theIngredient)
return output
}
knex('Meals')
.select('Meals.Name as mealName', 'Ingredients.*')
.innerJoin('MealsIngredients', 'Meals.Id', 'MealsIngredients.Meal')
.innerJoin('Ingredients', 'Ingredients.Id', 'MealsIngredients.Ingredient')
.where('Meals.Id', mealId)
.then(records => records.reduce(outputFormatter, {}))
Run Code Online (Sandbox Code Playgroud)
这将产生:
{
name: 'Spinach Pie',
ingredients: [
{ Id: 1, Name: 'Spinach', Type: 'Vegetable' },
{ Id: 2, Name: 'Garlic', Type: 'Vegetable' }
]
}
Run Code Online (Sandbox Code Playgroud)
我可能在大小写方面有些失误……我不习惯 PascalCase!