【问题标题】:Trouble adding "and" and "or" clauses in query through rails query interface通过rails查询接口在查询中添加“and”和“or”子句时遇到问题
【发布时间】:2017-07-31 08:42:05
【问题描述】:

我正在尝试通过 Rails 查询界面运行以下查询,但无法翻译我的逻辑。查询是

Select f.* from feeds f
Left join feed_items fi on fi.id = f.feedable_id
where 
  f.feedable_type in ('Homework', 'Datesheet')
  and
  (
    (fi.assignable_type = 'Level' and assignable_id IN (1)) or
    (fi.assignable_type = 'Student' and assignable_id IN (1)) or
    (fi.assignable_type = 'Section' and assignable_id IN (1)) 
  )

场景:

我在我的操作中收到以下参数哈希,其中包含将在我的查询中动态添加的过滤器

{"page"=>"1", "limit"=>"2", "type_filter"=>["Homework", "Datesheet"], "assignable_filter"=>{"Student"=>"[2]", "Section"=>"[1]", "Level"=>"[1]"}}

到目前为止,我所做的是加入表并为类型过滤器添加了 where 子句,但不确定如何动态添加 assignable_filters。这是我的 Rails 代码,options 在下面的代码中是 params

def get_feeds(options)
    base = Feed.includes(:feed_item)
    base = add_type_filters base, options
    base = add_assignable_filters base, options
    format_response base, options
end

def add_type_filters(base, options)
    type_filter = options[:type_filter]
    if !type_filter.nil? and type_filter.length > 0
      base = base.where('feedable_type IN (?)', options[:type_filter])
    end
    base
end

def add_assignable_filters(base, options)
    assignable_filter = options[:assignable_filter]
    if !assignable_filter.nil?
      assignable_filter.each do |key, value|
        # code for adding filters combined with or conditions
      end
      # wrap the or conditions and join them with an and in main where clause
    end
    base
end

PS 我正在使用 Rails 5

【问题讨论】:

  • 我注意到的第一件事:不是 feed 和 feed_items(一对多的关系吗?)。如果是,Feed.includes(:feed_items) 是正确的。
  • 在这里您可以看到如何在 Rails5 中进行 OR 查询:stackoverflow.com/questions/32753168/…
  • @haffla 它是一对一的关联
  • base = base.where('feedable_type IN (?)', options[:type_filter]) 应该是 base.where(feedable_type: options[:type_filter]) 这将构建一个“IN”子句。现在查询是"feedable_type in (\"[\"Homework\", \"Datesheet\"]\")" 因为Array 将被转换为String

标签: ruby-on-rails ruby queryinterface


【解决方案1】:

没有直接的动态构建查询的方法。我必须构造 where 字符串来解决问题。我目前的解决方案是

def get_feeds(options)
    params_hash = {}
    type_filters = add_type_filters options, params_hash
    assignable_filters = add_assignable_filters options, params_hash

    where = type_filters
    where = where ? "#{where} and (#{assignable_filters})" : assignable_filters

    base = Feed.eager_load(:feed_item).where(where, params_hash)
    format_response base, options
end

def add_type_filters(options, params_hash)
    type_filter = options[:type_filter]
    type_filter_sql = nil
    if !type_filter.nil? and type_filter.length > 0
      type_filter_sql = 'feeds.feedable_type in (:type_filter)'
      params_hash[:type_filter] = type_filter
    end
    type_filter_sql
end

def add_assignable_filters(options, params_hash)
    assignable_filter_sql = []
    assignable_filter = options[:assignable_filter]
    if !assignable_filter.nil?
      assignable_filter.each do |key, value|
        assignable_filter_sql.push("(feed_items.assignable_type = '#{key}' and feed_items.assignable_id IN (:#{key}))")
        params_hash[key.to_sym] = JSON.parse(value)
      end
    end
    assignable_filter_sql.join(' or ')
end

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多