我试图找到一种最简洁的方法,根据关联和搜索数组来选择记录。
我有一个Recipes
,其中有许多Ingredients
(通过连接表)我有一个Ingredient.ids
的array
搜索表单字段
要查找包含搜索数组中任何id的任何配方,我可以使用
例如1。filtered_meals = Recipe.includes(:ingredients).where("ingredients.id" => ids)
但是,我只想匹配所有成分都在搜索数组中找到的食谱。
例如2。
search_array = [1, 2, 3, 4, 5]
Recipe1 = [1, 4, 5, 6]
Recipe2 = [1, 3, 4]
# results => Recipe2
我知道我可以使用each
循环,类似于这样;
例如3。
filtered_meals = []
Recipes.each do |meal|
meal_array = meal.ingredients.ids
variable = meal_array-search_array
if variable.empty?
filtered_meals.push(meal)
end
end
end
return filtered_meals
这里的问题是分页。在第一个示例中,我可以使用.limit()
和.offset()
来控制显示多少个结果,但在第三个示例中,我需要添加一个额外的计数器,将其与结果一起提交,然后在页面更改时重新发送计数器,并在each.do
循环中使用.drop(counter)
。
这似乎太罗嗦了,有没有更好的方法来做到这一点?
5条答案
按热度按时间lp0sw83n1#
假设你使用的是
has_many through
& recipe_id,配料_id组合是唯一的。ih99xse12#
不如
您需要确保ids参数是按升序列出的,这样数组中元素的顺序也会匹配。
z6psavjg3#
Ruby on Rails Guide 2.3.3 - Subset Conditions
SELECT * FROM recipes WHERE (recipes.ingredients IN (1,2,3,4,5))
应导致:
SELECT * FROM recipes WHERE (recipes.ingredients IN (1,2,3,4,5))
个得双曲余切值.
31moq8wy4#
数组
&
运算符在这里是否适用?类似于:
这个方法比较数组,只返回两者都存在的元素,所以如果比较的结果等于配方数组,则所有元素都存在(显然,您可以进行一些重构,使该方法位于配方模型中)。
然后,您可以执行以下操作:
我不确定它是否通过你的示例三,但可能会对你有所帮助?让我知道它是否开始好,同时我会有更多的思考/如果它有用:)
qjp7pelc5#
我有一个类似的需求,并使用下面的模式解决了它。这是我的食谱模型中的方法。
这将返回所有所需成分都包含在成分数组中的每个配方。
Postgres '〈@'操作符是一个神奇的解决方案。array_agg函数创建一个包含每个配方的配料id的数组,然后向左指的bird操作符询问该数组中的所有唯一id是否都包含在右边的数组中。
使用array_agg函数需要将search_array转换为Postgres语法。
我的“食谱”模型有许多“配料”和“部分”。
我很想知道是否有人有更好的优化,或者知道如何避免我需要做的Postgres语法转换。