【问题标题】:Postgres LIKE in a rails application轨道应用程序中的 Postgres LIKE
【发布时间】:2016-10-15 15:38:23
【问题描述】:

我有这样的 Postgres LIKE 声明:

@favorites.find_each do |profiles|
  @related_profiles = Profile.where('name LIKE ?', '%' + profiles.name + '%')
end

我要做的是遍历favourites 变量并找到contain 名称中某些字符的所有配置文件。

例如,如果名称包含"jackson""jasson",则应找到名称"jasson jackson"

【问题讨论】:

    标签: ruby-on-rails ruby postgresql ruby-on-rails-4 rails-activerecord


    【解决方案1】:

    您要查找的查询类似于:

    Profile.where("name LIKE ?", "%#{profiles.name}%")
    

    但请注意,您的@related_profiles 可能未正确分配,因为结果与说的相同:

    Profile.where("name LIKE ?", "%#{@favorites.last.name}%")
    

    然而,我怀疑这是否是您所需要的。 另请注意,它将是一个 ActiveRecord::Collection,一个类似对象的数组。

    解决此问题的一种方法是初始化@related_profiles = [],然后在循环的每个点上,您可以这样做:

    @related_profiles += 
    Profile.where("name LIKE ?", "%#{profiles.name}%")
    

    或者另一种方式是:

    names = @favorites.map(&:name)
    query = names.map{|name| "name LIKE '%#{name}%'"}.join(" OR ")
    

    query = @favorites.map{|favorite| "name LIKE '%#{favorite.name}%'" }.join(" OR ")
    

    那么

    profiles = Profile.where(query)
    

    更新 根据@joshrumbut 的评论,我决定使用绑定参数重新实现。 但是,代码清晰度有点丢失,但是可以通过以下方式完成:

    names = @favorites.map(&:name)
    query = names.map{|favorite| "name LIKE ?" }.join(" OR ")
    profiles = Profile.where(query, *names.map{|name| ("%#{name}%")})
    

    根据@muistooshort 的评论,我删除了前两个查询中的引号,我认为这种方法看起来更简洁,正如他所建议的那样。来自docs

    Profile.where('name like any(array[?])', names.map { |s| "%#{s}%" })
    

    【讨论】:

    • 关于提问者的方法出了什么问题的背景很好,但我担心用这样的字符串连接构建查询。在我看来,像下面@Fist 那样使用参数绑定是更好的做法。
    • where('name like any(array[?])', names.map { |s| "%#{s}%" }) 是一个更简洁的选项 (docs)。此外,在占位符值中不需要前两个中的单引号(并且会导致问题),ActiveRecord 会为您正确转义。
    • 感谢@muistooshort,这种方法看起来确实更干净。更新答案以反映这些并适当归因。
    • 这仍然不起作用,如果我他们的变量是 jason jackson 并且我正在搜索 'jackson' 或只是 'jason' 这个配置文件不会显示只有当它的 'jason jackson' 然后配置文件将加载
    【解决方案2】:

    为了获得更好的此类搜索结果,您可以尝试使用 FTS(全文搜索)。

    Rails 有一个 gem 实现了这个功能:

    https://github.com/Casecommons/pg_search

    PgSearch 构建命名范围,利用 PostgreSQL 的全文搜索。

    在您的项目中安装此 gem 后,只需使用以下语句进行搜索:

    PgSearch.multisearch("jasson")
    

    其他选项是 Elasticsearch,您可以使用他为您的寄存器编制索引以获得更好的文本搜索。

    希望对你有帮助:)

    【讨论】:

      【解决方案3】:

      我将尝试使用 Postgres 模式和“OR”运算符 - postgres doc

      names = @favorites.map(&:name)
      Profile.where('name LIKE %(?)%', names.join('|'))
      

      【讨论】:

      • LIKE 不理解正则表达式交替运算符,您需要为此使用 SIMILAR TO 或 ~ (然后您必须担心转义正则表达式中的特殊内容) .
      猜你喜欢
      • 1970-01-01
      • 2020-06-08
      • 2011-07-31
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多