最近,我已经使用Hackalode设计了数据库模型或ERD。 因此,我目前面临的问题是基于当前的设计,我无法正确查询它。我用MYSQL学习了ERD,但确实知道Mongo不能正常工作
这个想法很简单,我想要一个食谱,里面有一系列的食材,而这些食材来自不同的馆藏。 配方还包括成分的测量。 (1汤匙糖)
还可以从配料列表中查询并找到包含配料的食谱
我希望这些集合具有多对多关系,并且配方可以使用数据库中已经存在的成分。
我只是不知道如何查询数据
我使用$ elemMatch进行了很多尝试并填充,结果我得到的只是空数组列表。
我希望有两种查询方式,我可以按配料名称或配方进行查询
我的期望结果将是这样
[{
id: ...,
name: ....,
description: ...,
macros: [...],
ingredients: [
{
id,
amount: ....,
unit: ....
ingredient: {
id: ....,
name: ....
}
}
}, { ... }]
但是没有得到
[]
答案 0 :(得分:1)
天哪,您的设计完全错误。您过度规范化了您的数据。我会做一些更简单的事情,并使用嵌入。其背后的原因是,先定义用例,然后再建模数据,以最有效的方式回答用例引起的问题。
当然,这只是一小部分摘录,但对于此示例来说就足够了。
好吧,第一个非常简单:
db.recipes.find()[.limit()[.skip()]]
现在,我们如何才能按成分查找?简单的答案:对成分名称(可能还有其他字段as you can only have one text index per collection)进行文本索引。然后,查询同样简单:
db.recipes.find({$text:{$search:"ingredient name"}})
“嘿,等等!我如何获得所有成分的清单?”让我们假设我们想要一个简单的成分列表,其中包含一些实际使用频率的数字:
db.recipes.aggregate([
// We want all ingredients as single values
{$unwind:"$Ingredients"},
// We want the response to be "Ingredient"
{$project:{_id:0,"Ingredient":"$Ingredients.Name"}
// We count the occurrence of each ingredient
// in the recipes
{$group:{_id:"$Ingredient",count:{$sum:1}}}
])
这实际上就足够了,除非您有数以百万计的食谱数据库。在这种情况下,您可能希望深入了解incremental map/reduce而不是汇总。 提示:您应该在配方上添加时间戳,以便能够使用增量映射/缩小。
如果您有几百个K到几百万个食谱,则还可以添加一个$out
阶段来预汇总数据。
Imho,定义测量没有意义。有茶匙,大汤匙,公制和英制尺寸,“打”之类的分组或“丁香”之类的规格。您真的不想相互转换甚至不想设置为有限数量的测量。一瓣大蒜多少盎司? ;)
底线:将其设置为自由文本字段,其中可能包含一些自动完成建议。
{
_id: new ObjectId(),
Name: "Surf & Turf Kebap",
Ingredients: [
{
Name: "Flunk Steak",
Measurement: "200 g"
},
{
Name: "Prawns",
Measurement: "300g",
Note: "Fresh ones!"
},
{
Name: "Garlic Oil",
Measurement: "1 Tablespoon",
Link: "/recipes/5c2cc4acd98df737db7c5401"
}
]
}
还有文本索引的示例:
db.recipes.createIndex({Name:"text","Ingredients.Name":"text"})
配方是您的基本数据结构,因为您的应用程序可能会基于某些条件来存储和提供它们。成分和度量(在有意义的范围内)可以轻松地从食谱中得出。那么,为什么还要麻烦地独立存储成分和测量值。它只会使您的数据模型不必要地复杂,而不会提供任何优势。
hth