【问题标题】:Query in Active record with an array of hash使用哈希数组查询活动记录
【发布时间】:2019-03-19 21:36:02
【问题描述】:

我在 Ruby 中有以下模型

class Entity < ActiveRecord::Base
  validates :account_type, presence: true
  validates :account_id, presence: true
end

我有一个称为帐户的哈希数组,例如:

[{'account_id':44, 'account_type':'user'},..,{'account_id':44, 'account_type':'other'}, {'account_id':88,
'account_type':'another'}]

所以我想要一种方法来获取与帐户数组的元素匹配的所有实体(account_id 和 account_type 两者同时)。

我尝试使用此代码:

entities = []
accounts.each do |account|
    entities << Entity.where(account_id: ActiveSupport::HashWithIndifferentAccess.new(account)['account_id'])
    .where(account_type: ActiveSupport::HashWithIndifferentAccess.new(account)['account_type'])
end

但是有一种方法可以提高效率??

【问题讨论】:

  • 既然要一条记录同时匹配两个属性,那我想不出更好的办法了。但是,可能有更好的方法来完成您尝试做的任何事情。也许您遵循的逻辑存在问题,导致您需要该查询,而不是查询本身。
  • 如果只通过字符串访问,是否需要转换为HashWithIndifferentAccess?两个where 子句看起来可以组合成where(account_id: account['account_id'], account_type: account['account_type]),或者如果您信任这些属性,也可以组合成where(account)。如果您不需要它们,也可以使用Entity.select('id, name').where() 来减少提取的字段数量。

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


【解决方案1】:

鉴于此:

[{'account_id':44, 'account_type':'user'}, {'account_id':44, 'account_type':'other'}, ... ]

你想要的 SQL 是:

select ...
where account_id = 44 and account_type = 'user'
   or account_id = 44 and account_type = 'other'
   or ...

请注意,SQL 的运算符优先级使其与以下内容相同:

select ...
where (account_id = 44 and account_type = 'user')
   or (account_id = 44 and account_type = 'other')
   or ...

您可以使用 ActiveRecord 构建类似的查询,但由于 #or 的工作方式,它有点麻烦:

accounts = your_array_of_hashes
entities = accounts.inject(Entity.none) { |memo, h| memo.or(Entity.where(h)) }

【讨论】:

    【解决方案2】:

    如果您使用的是 rails 5,您可以尝试or。像这样的

    entities = Entity.none
    items.each do |item|
      entities = entities.or(Entity.where(item))
    end
    

    这只是一个 SQL 查询,但如果数组很大,我不知道它是如何工作的。

    【讨论】:

      【解决方案3】:

      如果我遇到了你的问题,这应该可以解决:

      entities = accounts.map { |acc| Entity.where(account_id: acc['account_id'], account_type: acc['account_type']) }
      
      

      让我解释一下发生了什么:

      • 首先,map 方法返回一个数组,将所有与数据库中任何内容匹配的条目都匹配
      • map 与帐户数组进行交互,就像 each 一样,这意味着它将帐户中的数据带到 where 查询中
      • commawhere 之间的条件也适用于比较,除非您正在执行or,在这种情况下我想您可以使用以下语法:where('account_id = :id or account_type = :type', id: acc['account_id'], type: acc['account_type'])

      【讨论】:

        猜你喜欢
        • 2016-08-18
        • 1970-01-01
        • 2017-12-10
        • 1970-01-01
        • 1970-01-01
        • 2020-07-13
        • 2018-04-28
        • 2014-02-01
        • 1970-01-01
        相关资源
        最近更新 更多