根据所有关联成员过滤记录
Posted
技术标签:
【中文标题】根据所有关联成员过滤记录【英文标题】:Filtering records based on all members of association 【发布时间】:2017-08-23 20:47:30 【问题描述】:我有一个名为Story
的模型,它有——并且属于许多——标签。我正在尝试创建基于故事属性仅显示某些故事的功能。我通过链接where()
s 来做到这一点:
q = Story.where(condition1)
q = q.where(condition2)
...等等。我希望能够过滤的一件事是标签,起初我尝试如下:
q = q.joins(:tags)
q = q.where(tagCondition1)
q = q.where(tagCondition2)
...
但是,这只查找具有匹配所有条件的单个标签的故事。我想找到至少有一个标签与每个条件匹配的所有故事。也就是说,目前如果我有条件LIKE %al%
和LIKE %be%
,它将匹配一个带有标签'alpha beta'
的故事;我希望它还可以匹配带有标签 'alpha'
和标签 'beta'
的故事。
【问题讨论】:
什么数据库?如果您使用的是 postgres,有很多选择 - ***.com/questions/4928054/… 在 SQL 端,您必须多次加入同一个表。不确定 Rails 能否很好地处理这种情况。 我已经在使用 SIMILAR TO 进行文本搜索,但我不确定它在这里有什么帮助? 要么拆分字符串并搜索组件,要么使用全文搜索。 【参考方案1】:也许您需要以下内容来匹配多个条件:
q.where([tagCondition1, tagCondition2, ...])
【讨论】:
【参考方案2】:您可以使用HAVING
进行计数。
class Story < ActiveRecord::Base
has_and_belongs_to_many :tags
def self.with_tags(*tags, min: 1)
joins(:tags)
.where(tags: name: tags )
.group('story.id')
.having("count(*) = ?", min)
end
end
用法:
params[:tag] = "foo bar baz"
Story.with_tags(params[:tag], *params[:tag].split)
将包括带有任何标签["foo bar baz", "foo", "bar", "baz"]
的故事。
【讨论】:
我看不懂这段代码。 min 代表什么? 最小匹配数。如果你这样做Story.with_tags("foo", "bar", "baz", min: 2)
,它只会返回 3 个标签中至少有 2 个的故事
如果我理解正确,如果一个标签匹配两个或多个条件,这将无法正常工作;即使两个条件匹配,此标记也只会将计数增加 1。
否 - 它是一个左连接,因此它只会返回至少具有列表中提供的标签之一的故事。如果设置min: 2
,则需要两个标签。
***.com/questions/36131803/…【参考方案3】:
查询错误。由于您使用的是 AND 并且您想匹配第一个 OR 第二个条件。也许你应该使用类似
where("tags.field like '%al% or tags.field like '%be%'")
【讨论】:
嗯,我想到了这一点,但问题是它会找到标签匹配一个条件的故事,即使其他条件都不匹配。我想匹配所有条件,只是不一定在同一个标签中。【参考方案4】:好的,这就是我最终做的事情:(为任何使用谷歌搜索并遇到类似问题的人添加):
conditions.each do |condition|
q_part = select('1').from('stories_tags')
q_part = q_part.where('stories_tags.story_id = stories.id')
q_part = q_part.where('stories_tags.name SIMILAR TO ?', condition)
q = q.where("EXISTS (#q_part.to_sql)")
end
【讨论】:
以上是关于根据所有关联成员过滤记录的主要内容,如果未能解决你的问题,请参考以下文章
根据子表中的“当前”值过滤 belongsToMany 记录