Я пытаюсь реализовать бесплатные запросы к лазерной базе данных.Например: дать все кадры с энергией> 20 Дж и продолжительностью <150 фс и ... </p>
Мой подход заключается в том, чтобы сначала найти все кадры с энергией> 20 Дж, а затем применить условие длительности <150 фс к этим кадрам.И так далее, пока все параметры поиска не будут обработаны. </p>
ss.ssps.each do |ssp|
selectedShots =
selectedShots.where("instancevalues.name = '#{ssp.instancevalue_name}'")
.where("instancevalues.data_numeric #{ssp.operator} #{ssp.value}")
end
Это работает, как и ожидалось, для одного параметра поиска.Оператор SQL выглядит следующим образом:
SELECT `shots`.* FROM `shots` WHERE (instancevalues.name = 'Energy')
AND (instancevalues.data_numeric > 20.0)
С двумя параметрами поиска я бы ожидал, что Rails сначала обработает первый параметр и создаст подмножество снимков, как описано выше.После этого применить второй параметр.
Вместо этого Rails генерирует один SQL-оператор вида
SELECT `shots`.* FROM `shots` WHERE
(instancevalues.name = 'Energy')
AND (instancevalues.data_numeric > 20.0)
AND (instancevalues.name = 'Duration')
AND (instancevalues.data_numeric < 150.0)
Результат, конечно, пуст.Как я могу реализовать пошаговую фильтрацию в рельсах?
ОБНОВЛЕНИЕ:
Я пытался объяснить суть проблемы, поэтому не использовал деталимодель.Но, возможно, это упрощение препятствует альтернативному решению.
У меня есть модели:
class Shot < ActiveRecord::Base
belongs_to :experement
has_many :instancevaluesets
has_many :instances, :through => :instancevaluesets
has_many :instancevalues, :through => :instancevaluesets
class Instancevalueset < ActiveRecord::Base
belongs_to :shot
belongs_to :instance
has_many :instancevalues
class Instancevalue < ActiveRecord::Base
# instancevalueset_id :integer(38) not null
# name :string(256) not null
# data_numeric :decimal(, )
belongs_to :instancevalueset
После каждого лазерного выстрела будет создаваться новый выстрел в дБ.Модель Instancevalueset подключает снимок к устройству (экземпляру).Физическое устройство создает запись для себя после выстрела.Устройства записывают результаты измерения в значениях instance с помощью instancevaluesset_id als FK.Моя задача - найти кадры, которые соответствуют параметрам поиска, примененным к значениям intance (результатам измерений).
Мой оригинальный код:
ss.ssps.each do |ssp|
selectedShots = **selectedShots.joins(:instancevalues)**
.where("instancevalues.name = '#{ssp.instancevalue_name}'")
.where("instancevalues.data_numeric #{ssp.operator} #{ssp.value}")
end
Предположим, набор снимков [a, b, c, d, e, f].Снимки [a, c, e] имеют энергию> 20 Дж, поэтому после первого ssp я хочу получить [a, c, e].Теперь я хочу отфильтровать короткие импульсы из этого набора.Выстрел e на длинный T = 200fs.Итак, во 2-й итерации я хочу применить ssp к [a, c, e] и получить [a, c].
Идея @Mark хороша, но она возвращает массив запросов, примененных к БД, а не к предыдущему набору.
selectedShots = ss.ssps.map do |ssp|
selectedShots.joins(:instancevalues)
.where("instancevalues.name = '#{ssp.instancevalue_name}'")
.where("instancevalues.data_numeric #{ssp.operator} #{ssp.value}")
end
Если было бы возможно выполнить слияние ANDмассива, это решило бы мою проблему.Но если я проверю:
selectedShots.last.merge(selectionShots.first)
, я получу снова:
....WHERE (instancevalues.name = 'Energy')
AND (instancevalues.data_numeric > 20.0)
AND (instancevalues.name = 'Duration')
AND (instancevalues.data_numeric < 150.0)