根据所有关联成员过滤记录

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 记录

DataGridView列表有两行记录,如何根据id过滤出其中一条记录?

sql 如何过滤重复记录

无法根据 Informix 中的日期过滤器过滤记录

根据上下文源将 Serilog 日志过滤到不同的接收器?

如何根据前一页选择过滤 Telerik Grid