我正在尝试构建一个菜谱查找应用程序(PERN stack),就像SuperCook,但我的 postgres 表遇到了一些问题。
所需结果的简短描述。我希望用户选择一些成分并返回只能使用这些成分制作的食谱。
我使用 pgadmin 从 Recipe Dataset 导入表并设置我的 Nodejs 服务器和路由。
我的问题是我不知道如何返回仅包含所选成分的食谱。
据我所知,WHERE、LIKE 和逻辑运算符无法帮助我(但我是初学者,所以我知道的不多),因为使用它们将返回包含所选成分 + 任何其他成分的食谱。
对于此类问题,我们唯一关心的列是 NER 列,因为它仅包含成分。我看到它们写得像一个javascript对象,例如:
"[""sesame seed"", ""soy sauce"", ""honey"", ""vegetable cooking spray"", ""thin green onion strips"", ""grated ginger"", ""chicken""]"
在 pgAdmin 中出现如下:
["sesame seed", "soy sauce", "honey", "vegetable cooking spray", "thin green onion strips", "grated ginger", "chicken"]
问题:如何从我的表格中仅选择包含完全所选成分或至少组合其中无特定顺序的食谱?
例如:
输入:鸡肉,黄油,洋葱,大蒜
输出:NER配方:
["butter", "chicken", "garlic", "onion"]
或带有NER的食谱:
["butter", "chicken"]
或带有NER的食谱:
["garlic", "chicken"]
等
一种选择是使用 json 函数将您的配料(用户的和菜肴的)排列成行。通过这种方式,您可以加入每种成分的数据,您可以计算出您拥有的成分数量与所需成分总数的比较,并获得其百分比。您还可以提供缺少成分的清单。
WITH -- S a m p l e D a t a :
ingredients ( id, dish, ner ) As
( Select 1, 'Jewell Ball''S Chicken', '["cream of mushroom soup", "beef", "sour cream", "chicken breasts"]' Union All
Select 2, 'Creamy Corn', '["frozen corn", "pepper", "cream cheese", "garlic powder", "butter", "salt"]' Union All
Select 3, 'Chicken Funny', '["chicken gravy", "cream of mushroom soup", "chicken", "shredded cheese"]' Union All
Select 4, 'Nolan''S Pepper Steak', '["oil", "tomatoes", "green peppers", "water", "onions", "worcestershire sauce"]' Union All
Select 5, 'Yor sample dish', '["butter", "chicken", "garlic", "onion"]'
),
...使用 json,将菜肴成分转置为行...
dish_ingredients As
( Select i.id, i.dish, Replace(json_array_elements(i.ner::json)::text, '"', '') as dish_ingredient
From ingredients i
),
...不知道您将如何提供用户成分数据,所以我将您的成分问题列表放入 cte 中,并执行与上面相同的操作以将它们排成行....
user_input As
( Select Replace(json_array_elements( array_to_json(string_to_array('chicken, butter, onion, garlic', ', ')) )::text, '"', '') as user_ingredient
),
...创建另一个 cte 来组合菜肴和用户成分,为使用它们的不同选项准备数据(有或没有成分、所需的总成分、百分比...)
grid As
( Select d.id, d.dish, dish_ingredient, ui.user_ingredient,
Case When ui.user_ingredient Is Null Then 1 End as flag_have_not,
Case When ui.user_ingredient Is Not Null Then 1 End as flag_have,
--
Count(Case When ui.user_ingredient Is Not Null Then d.id End)
Over(Partition By d.id) as cnt_have,
Count(d.id) Over(Partition By d.id) as cnt_dish_ingredient,
--
Round(Count(Case When ui.user_ingredient Is Not Null Then d.id End)
Over(Partition By d.id)::Decimal
* 100 / Count(d.id) Over(Partition By d.id)
, 2) as pct_match
From dish_ingredients d
Left Join user_input ui ON( Position(ui.user_ingredient In d.dish_ingredient) > 0 )
)
...这是主要的sql - 获取用户拥有50%或更多食材的菜肴...
-- M a i n S Q L :
Select id, dish, Max(pct_match) as pct_match,
string_agg(Case When flag_have_not = 1 Then dish_ingredient End, ', ' Order By user_ingredient) as missing_ingredients
From grid
Where pct_match >= 50
Group By id, dish
/* R e s u l t :
id dish pct_match missing_ingredients
-- ------------------ --------- ----------------------------------------------------
3 Chicken Funny 50.00 cream of mushroom soup, shredded cheese
5 Yor sample dish 100.00 null */
注意:
您应该注意多词成分和可能的错过匹配或错误匹配以及其他问题(可能使用 Like 进行匹配)。下面是网格 cte 结果集:
/* R e s u l t : ( grid )
id dish dish_ingredient user_ingredient flag_have_not flag_have cnt_have cnt_dish_ingredient pct_match
-- ------------------------- ------------------------ ----------------- ------------- --------- -------- ------------------- ---------
1 Jewell Ball'S Chicken cream of mushroom soup null 1 null 1 4 25.00
1 Jewell Ball'S Chicken beef null 1 null 1 4 25.00
1 Jewell Ball'S Chicken sour cream null 1 null 1 4 25.00
1 Jewell Ball'S Chicken chicken breasts chicken null 1 1 4 25.00
2 Creamy Corn frozen corn null 1 null 2 6 33.33
2 Creamy Corn pepper null 1 null 2 6 33.33
2 Creamy Corn cream cheese null 1 null 2 6 33.33
2 Creamy Corn garlic powder garlic null 1 2 6 33.33
2 Creamy Corn butter butter null 1 2 6 33.33
2 Creamy Corn salt null 1 null 2 6 33.33
3 Chicken Funny chicken gravy chicken null 1 2 4 50.00
3 Chicken Funny cream of mushroom soup null 1 null 2 4 50.00
3 Chicken Funny chicken chicken null 1 2 4 50.00
3 Chicken Funny shredded cheese null 1 null 2 4 50.00
4 Nolan'S Pepper Steak oil null 1 null 1 6 16.67
4 Nolan'S Pepper Steak tomatoes null 1 null 1 6 16.67
4 Nolan'S Pepper Steak green peppers null 1 null 1 6 16.67
4 Nolan'S Pepper Steak water null 1 null 1 6 16.67
4 Nolan'S Pepper Steak onions onion null 1 1 6 16.67
4 Nolan'S Pepper Steak worcestershire sauce null 1 null 1 6 16.67
5 Yor sample dish butter butter null 1 4 4 100.00
5 Yor sample dish chicken chicken null 1 4 4 100.00
5 Yor sample dish garlic garlic null 1 4 4 100.00
5 Yor sample dish onion onion null 1 4 4 100.00 */