简体   繁体   English

如何通过多个值过滤模型字段(或)

[英]How to filter a models field by multiple values (OR'd)

I have a model say Book which has the following scope function: 我有一个模型说Book ,它具有以下作用域函数:

scope :author, lambda { |author|
    return where(nil) unless author.present?
    joins(:author).where('author.id' => author)
  }

This can filter the Books with only ONE author value. 这样可以仅使用一个作者值来过滤“书籍”。 What I want to do is that I am passed a array from a JavaScript file which is a list of authors for example: ["harry", "doyle", "alex", "parrish"] and I want to be able to find all the books who has ANY of these authors (so an OR query here). 我想做的是从JavaScript文件(例如["harry", "doyle", "alex", "parrish"]的作者列表中传递了一个数组["harry", "doyle", "alex", "parrish"] ,我希望能够找到具有这些作者中任何一位的所有书籍(因此请在此处进行OR查询)。 Note each book can have multiple authors. 请注意,每本书可以有多位作者。

I have tried the following function but it simply gives me all the books rather than filtering correctly as I stated above. 我尝试了以下功能,但它只是给我所有的书,而不是如上所述的正确过滤。

scope :authors_multiple, lambda { |authors|
  @results = Book
  authors.each do |auth|
    @results = @results.author(auth)
  end
  return @results
}

model Author (extract): 示范作者(摘录):

class Author < ApplicationRecord
  has_and_belongs_to_many :books, uniq: true
  ....

model Book (extract): 样书(摘录):

class Book < ApplicationRecord
  has_and_belongs_to_many :authors, uniq: true
  ....

Can you please help me understand what I am doing wrong or what may be the right way to do it. 您能否帮助我了解我做错了什么或做错了什么正确方法。 Thanks in advance. 提前致谢。

authors = ["harry", "doyle", "alex", "parrish"]  
Book.where(author: authors)

or 要么

authors = ["harry", "doyle", "alex", "parrish"]  
auths = Author.where(name: authors)
Book.where(author: auths)

This assumes that an Author has many Books. 假设作者有很多书。 You can learn more about model associations here: https://guides.rubyonrails.org/association_basics.html 您可以在此处了解有关模型关联的更多信息: https : //guides.rubyonrails.org/association_basics.html

First you need to get your Author records. 首先,您需要获取Author记录。 How this is done depends on your schema and data, but it will be something akin to: 如何完成此操作取决于您的架构和数据,但这将类似于:

author_names = ["harry", "doyle", "alex", "parrish"]

Then one of the following: 然后执行以下操作之一:

authors = Author.where(name: author_names)
authors = Author.where("name ILIKE ANY ( array[?] )", author_names.map { |name| "%#{name}%" })

Something that gets us an ActiveRecord::Relation of the authors we need. 使我们得到需要的作者的ActiveRecord::Relation的东西。 Once we have the authors we can merge that with our books to get all the books we want: 一旦我们有了作者,我们可以将其与我们的书合并以获得我们想要的所有书:

books = Book.joins(:authors).merge(authors)

Note that the join is on the plural author s . 请注意,连接是在多作者 Rails will know to join through the join table (should be authors_books by default) to the authors table. Rails将知道通过连接表(默认情况下应该为authors_books )连接到authors表。

You get an array of author names, right? 您会得到一系列的作者姓名,对不对?

scope :by_author, lambda { |names|
  # if you have a chance to get blank values you need to reject them
  names.reject!(&:blank?) if names.is_a? Array

  joins(:authors).where(authors: { name: names }).distinct if names.present?
}

It should work properly with array or string argument 它应该与数组或字符串参数一起正常工作

Book.by_author(["harry", "doyle"])
Book.by_author("harry")

Try Below code: 尝试以下代码:

authors = ["harry", "doyle", "alex", "parrish"]    
Book.joins(:authors).where(:authors => {:name => authors})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM