ActiveRecord Найти все не сортировка по идентификатору? - PullRequest
18 голосов
/ 13 февраля 2011

У меня возникла странная проблема в развертывании Heroku, которую я не могу воспроизвести локально.В основном, когда я нахожу все по определенной модели вместо сортировки по идентификатору, кажется, что они возвращаются в произвольном порядке

Обычно записи выглядят так:

>> Model.all

=> [<model id: 2>,<model id: 1>,<model id: 3>,<model id: 4>,<model id: 5>]

... и т. д.

Если я явно позвоню Model.order("id ASC"), он вернет модели, как и ожидалось.

Что дает?Почему бы найти все не вернуть объекты в порядке убывания идентификатора?

Ответы [ 5 ]

26 голосов
/ 13 февраля 2011

Заказ по идентификатору не гарантирован по умолчанию.Это зависит от базы данных, как упорядочивается неупорядоченный запрос (обычно он не указан).Если вы хотите, чтобы ваши результаты были упорядочены, вам нужно указать явный порядок с помощью order, как вы сделали:

Model.order(id: :asc)

Обратите внимание, что упорядочение по idдолжно быть сделано только если вы хотите детерминированный порядок.Если вы хотите сделать заказ по времени, используйте created_at или updated_at (ничто не гарантирует, что id s упорядочены в хронологическом порядке).Если вы хотите, чтобы все запросы всегда были упорядочены, вы можете использовать default_scope, но обычно его следует избегать.

8 голосов
/ 13 февраля 2011

В SQL таблицы считаются множествами записей, а не списками записей, и запрос "выборки" не гарантирует возврата записей в любом конкретном порядке, если только оговорка 'order by' специально включена. Вы можете иногда видеть, что результаты возвращаются в определенном порядке, но это не значит, что вы можете или должны предполагать, что так будет всегда.

Используя ActiveRecord, вы можете принудительно использовать предложение order by по умолчанию, указав область действия по умолчанию. В общем, это плохая идея, потому что это заставит сервер выполнять больше работы, чтобы дать вам отсортированный набор результатов, даже если он вам не нужен. Кроме того, сортировка в поле 'id' обычно неуместна, поскольку смысл 'id' должен быть непрозрачным идентификатором записи без цели или значения, кроме как быть уникальным для данной записи в таблице.

1 голос
/ 23 марта 2015

Просто обновление отличного ответа Эндрю (извините, у меня недостаточно репутации, чтобы добавить его в качестве комментария), поддержка вызова #default_scope без блока теперь удалена. В настоящее время допустимый синтаксис в модели:

default_scope { sort(id: 'ASC') }
0 голосов
/ 21 июня 2019

Вы должны явно заказать ваши запросы.Как правило, в базе данных нет гарантированного или фиксированного заказа.

Кроме того, вы должны не использовать default_scope (см .: 1 , 2 , 3 ).Вместо этого используйте нормальный объем или явное упорядочение:

class Model < ApplicationRecord
  scope :oldest_first { order(created_at: :asc) }
end

Model.oldest_first.limit(10)
Model.order(created_at: :desc).limit(10)
0 голосов
/ 14 февраля 2011

Хорошо, для записи мои тесты дали следующее объяснение: в PostgreSQL (и, возможно, других) метод "100" * всего "*", по-видимому, возвращает вещи в порядке их последнего сохранения (см. Комментарий ниже).Таким образом, последний сохраненный элемент возвращается последним, а самый старый сохраненный элемент возвращается первым.Мне удалось «исправить» порядок, сохранив все модели в порядке идентификаторов.

Эта проблема не существует в SQLite и т. Д., Но ответ Стива имеет смысл (нет никакой гарантии, что записи вернутся в определенном порядке).порядок).Кроме того, ответ Эндрю Маршалла действительно работает.

...