存储和查询具有多个相关实体的 PostgreSQL 数据库实体?



设计一个PostgreSQL数据库,该数据库将由Node API使用Sequelize查询。目前,我有一个名为recipes的表,其中包含名为ingredientsinstructions的列。这些列以给定的字符串数组的形式存储,如{Tomatoes, Onions}.

这种存储方法适用于在客户端简单地获取和呈现配方。但是它不适用于模糊搜索查询,因为使用 Sequelize 我所能做的就是ingredients: { [Op.contains] : [query] }.因此,如果用户输入tomatoes则无法编写"模糊"搜索查询,该查询将返回带有成分Tomatoes的食谱。

然后我在PostgreSQL文档中读到了这个:

数组

不是集合;搜索特定的数组元素可能是数据库设计错误的标志。请考虑使用单独的表,其中每个项目都是数组元素。这将更容易搜索,并且可能会更好地缩放大量元素。

现在我正在考虑将ingredientsinstructions存储为单独的表,但我有几个问题。

1(由于配方可以有多个与之相关的成分,我是否应该只为每个成分使用外键和续集hasMany关系?这对我来说似乎是正确的,除了我现在每次创建使用该成分的新配方时都可能复制常见成分。

2(编写模糊搜索查询的最佳方法是什么,以便用户可以搜索recipes表的主要列(例如titledescription( 并另外将其查询应用于instructions表和ingredients表?

从本质上讲,我想最终将一个模糊的搜索查询应用于三个表,看起来像这样......

const recipes = await req.context.models.Recipe.findAll({
where: {
[Op.or]: [
{ title: { [Op.iLike]: '%' + query + '%' } },
{ description: { [Op.iLike]: '%' + query + '%' } },
{ ingredients: { ingredient: { [Op.iLike]: '%' + query + '%' } } },
{ instructions: { instruction: { [Op.iLike]: '%' + query + '%' } } }
]
}
});

谢谢!

我已经这样做了,我碰巧在我的节点层中使用了 graphql,并且我有执行此类事情的过滤器对象。你只需要在你的Recipie.findAll中有一些包含语句。在初始 where 子句之后,您可以在其中评估您是在搜索标题还是描述或两者兼而有之。我发送了带有前缀的搜索参数,我可以去掉它告诉我我想在它们上使用什么续集 op,并且只是通过一个实用方法运行我的参数来创建我的 where 子句,但我知道有很多方法可以剥皮那只猫。我只是不想用大量的硬编码操作和条件子句弄乱我的解析器......您的包含可能如下所示

include: [{
model: models.Ingredient,
as: 'Ingredients',
through: { some join table specifying keys where necessary since this 
is many to many }
where: {some conditional code around your search param},
}, {
model: models.Instruction,
as: 'Instructions',
where: {some conditional code around your search param},
}],

续集文档中有多个包含或嵌套包含的良好文档,但从我上面看到的内容来看,您对需要做什么有相当好的了解。 为了使事情复杂一点,我会从 recipie(标题、描述(中搜索您的字段开始,然后再添加包含并使其正常工作,然后您希望如何形成您的 where 子句会更清楚一些。

Alternativley.. 您可以跳过包含并在模型中编写关联,并使用 getter 调用它们并将 where 子句传递给那些......我也这样做,现在再次记录得很好的东西..续集确实提升了他们的游戏水平

Recipie.associate = function (models) {
models.Recipie.hasMany(models.Ingredient, { as: 'Ingredients', through: "recipie_ingredient" foreignKey: 'recipie_id'});
};

现在你有一个成分的吸气剂,如果你声明属于 ToMany 在成分模型中回到食谱,那么你也会在那里有一个吸气剂,你可以通过 where 子句将你的搜索字符串传递给那个,并获取所有具有给定成分或成分列表类型的东西的食谱......清澈如泥?

最新更新