Порядок ActiveRecord по внешнему массиву - PullRequest
11 голосов
/ 14 декабря 2011

У меня есть массив идентификаторов, хранящихся в каком-то внешнем хранилище (rails cache или redis). В действии контроллера я выбираю эти данные и выбираю объект, используя его, то есть

ids = [5, 1, 17, 84] # really fetched from external source
result = MyModel.where(:id => ids)

Я также хочу, чтобы он был упорядочен точно так же, как идентификаторы в array_of id:

ids == result.map(&:id) # => true

В качестве обходного пути я использую сортировку по функции mysql FIELD:

MyModel.where(:id => ids).order("FIELD(id, #{ids.join ', '})")

Но мне не нравится этот подход, поскольку он специфичен для mysql и создает очень длинные запросы в случае большого массива ids. Есть ли лучший, независимый от DB способ сделать это? Извлечение несортированных данных из БД и сортировка на стороне ruby ​​нежелательны, поскольку они дороги и трудны для использования при разбивке на страницы.

Спасибо.

Ответы [ 3 ]

12 голосов
/ 13 марта 2015

Я только что выпустил гем ( order_as_specified ), который позволяет вам выполнять собственный порядок SQL следующим образом:

MyModel.where(id: ids).order_as_specified(id: ids)

Он возвращает отношение ActiveRecord и, следовательно, может быть связан с другимиметоды:

MyModel.where(id: ids).order_as_specified(id: ids).limit(3)

Если вам интересно, под капотом он строит:

... ORDER BY ID='5' DESC, ID='1' DESC, ID='17' DESC, ID='84'  DESC
7 голосов
/ 13 марта 2014

Если вы не возражаете против получения массива вместо коллекции ActiveRecord, вы можете использовать:

result = MyModel.find(ids).sort_by {|m| ids.index(m.id)}
0 голосов
/ 14 декабря 2011

Если порядок массива всегда один и тот же, вы можете добавить столбец кэшированного порядка в таблицу базы данных.

MyModel.order ("cached_order")

...