Rails / ActiveRecord: порядок возврата с ActiveRecord # find (Array) - PullRequest
3 голосов
/ 25 января 2010

Я использую Ruby on Rails / ActiveRecord и у меня проблемы с вызовом ActiveRecord # find. Я храню в базе данных сериализованный массив идентификаторов недавно просмотренных документов. Идентификаторы хранятся в порядке убывания того, когда они последний раз просматривались, поэтому последний из просмотренных идентификаторов документа находится первым в массиве. Массив включает максимум 10 идентификаторов.

Пока все хорошо. Проблема в том, что ActiveRecord # find (Array), похоже, игнорирует порядок, в котором идеи появляются в массиве. Поэтому, если я наберу Document.find ([1, 2, 3]), я получу тот же результат, что и Document.find ([3, 2, 1]).

Тогда мой вопрос заключается в следующем: как получить массив результатов ActiveRecord в том же порядке, что и идентификаторы, которые я передал в #find? Или, если ActiveRecord не делает это возможным напрямую, как я могу отсортировать получившийся массив по факту?

Большое спасибо за любые ответы, которые могут дать люди!

Ответы [ 3 ]

11 голосов
/ 25 января 2010

ActiveRecord - это интерфейс к вашей базе данных, который возвращает вам записи в том же порядке, в котором база данных возвращает их. Если вы не предоставите параметр 'order', тогда возвращаемый заказ будет (фактически) случайным.

Если ваш заказ по идентификатору по возрастанию или по убыванию:

results = SomeModelName.find([1,2,3], :order => "id") # ascending order
results = SomeModelName.find([1,2,3], :order => "id desc") # descending order

Если порядковый номер идентификатора не возрастает или не убывает:

ids = [1, 3, 2]
r = SomeModelName.find(ids)
results = ids.map{|id| r.detect{|each| each.id == id}}
1 голос
/ 13 августа 2011

обсуждение того, как делать это на стороне базы данных, не очень хорошо для приложения rails: (

[03:24] <brauliobo> how can I select ids in an specified order? i would like to do something like "select * from blocks where id in (349120, 349118, 349117) order by id (349120, 349118, 349117)", but the order return is the db order.
[03:25] <RhodiumToad> if you have only a few ids you can do this:
[03:26] <RhodiumToad> select * from blocks where id in (349120, 349118, 349117) order by id <> 349120, id <> 349118, id <> 349117;
[03:26] <RhodiumToad> if you have more you may prefer this:
[03:27] <RhodiumToad> select * from blocks join (select i, (ARRAY[349120, 349118, 349117])[i] as id from generate_series(1,3) i) s on (s.id=blocks.id) order by s.i;
[03:27] <brauliobo> nice, it is a lot of ids
[03:28] <brauliobo> do you think this second query is "cross" sql compliant?
[03:28] <RhodiumToad> no, it's not
[03:28] <RhodiumToad> there is a standard-compliant way of doing it but that's still not supported by most of the dbs you're likely to use other than postgres
[03:29] <brauliobo> so this is the standard-compliant way?
[03:29] <RhodiumToad> no
[03:30] <RhodiumToad> generate_series is not in the standard
[03:30] <RhodiumToad> the standard way would be something like this:
[03:31] <RhodiumToad> select * from blocks join unnest(array[349120, 349118, 349117]) with ordinality as u(id,i) on (blocks.id=u.id) order by u.i;  but pg does not yet support the "with ordinality" clause
[03:32] <brauliobo> interesting, which sql standard it it?
[03:34] <RhodiumToad> 2008
0 голосов
/ 25 января 2010

ActiveRecord использует порядок сортировки, предоставленный базовой базой данных, что означает, что вам нужно предоставить «ORDER BY».

Для заказа по ID вы должны использовать

find(:all, :order => "id")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...