0

I'm on rails 4 and using Postres 9.4. My code currently is like:

array1 = Model.where(some_condition1).ids
array2 = Model.where(some_condition2).ids

Is there a way to get the same results with only one database read? In the form:

master_array = <the solution>

and each element of master_array is of something like the form (where I know which conditions the id satisfied):

[id, some_condition1?, some_condition2?]

so I can quickly do:

array1 = master_array.select { |n| n[1] }.map { |n| n[0] }
array2 = master_array.select { |n| n[2] }.map { |n| n[0] }
pthamm
  • 1,841
  • 1
  • 14
  • 17

3 Answers3

1

Let's change the SELECT to return the id plus two custom columns that represent a boolean for each condition. This will populate adorable little models with only the attributes you asked for, but that respond to your custom column names as methods.

results = Model.select("id, #{some_condition1} as condition1, #{some_condition2} as condition2").where("(#{some_condition1}) OR (#{some_condition2}")

So then just check the columns you named condition1 (or whatever you want to call them) and create your arrays based on the models that return true.

array1 = results.select(&:condition1).map(&:id)
array2 = results.select(&:condition2).map(&:id)
devpuppy
  • 822
  • 9
  • 8
0

Depends a bit on the complexity of your conditions, but for rather simple conditions I suggest you query with OR condition

results = Model.where('(some_condition1) OR (some_condition2)')

Then use Array select to split into two arrays:

array1 = results.select {|itm| itm == 'something which covers some_condition1'}
array2 = results.select {|itm| itm == 'something which covers some_condition2'}
siax
  • 150
  • 7
-1

Ideally you would want something like this:

Model.where(some_condition1).or.where(some_condition2).pluck(:id)

but that's not available, yet. You could use arel_table as well but what I would do is explicitly write the query.

Model.where('some_condition1 = ? OR some_condition2 = ?', condition1, condition2).pluck(:id)
Community
  • 1
  • 1
Mitch
  • 239
  • 2
  • 8