ActiveRecord Найти все не сортировки по ID?
У меня странная проблема в развертывании Heroku, которую я не могу дублировать локально. В основном, когда я нахожу все на определенной модели вместо сортировки по ID, кажется, что они возвращают их в любом порядке.
Обычно записи выглядят так:
>> Model.all
=> [<model id: 2>,<model id: 1>,<model id: 3>,<model id: 4>,<model id: 5>]
... и т.д.
Если я явно вызываю Model.order("id ASC")
, он возвращает модели, как ожидалось.
Что дает? Почему бы всем не возвращать объекты в порядке убывания идентификатора?
Ответы
Ответ 1
Заказ по идентификатору не гарантируется по умолчанию. Это зависит от базы данных, как упорядочивается неупорядоченный запрос (обычно это не указано). Если вы хотите, чтобы ваши результаты были упорядочены, вам нужно указать явный порядок с order
, как вы это сделали:
Model.order(id: :asc)
Также обратите внимание, что упорядочение по id
должно выполняться только в том случае, если вы хотите детерминированный порядок. Если вы хотите упорядочить по времени, используйте created_at
или updated_at
(ничто не гарантирует, что id
упорядочен в хронологическом порядке). Если вы хотите, чтобы все запросы всегда были упорядочены, вы можете использовать default_scope
, но обычно его следует избегать.
Ответ 2
В SQL таблицы считаются наборами записей, а не списками записей, а запрос "select" не гарантированно возвращает записи в каком-либо конкретном порядке, если специально не указано предложение "order by". Возможно, вам удастся увидеть, что результаты иногда появляются в определенном порядке, но это не значит, что вы можете или должны предположить, что это всегда будет так.
Используя ActiveRecord, вы можете принудительно по умолчанию использовать параметр order by by, если хотите, указав область по умолчанию. В общем, это плохая идея, потому что это заставит сервер делать больше работы, чтобы дать вам отсортированный набор результатов, даже если вам это не нужно сортировать. Кроме того, сортировка в поле "id" обычно неприемлема, так как точка "id" должна быть непрозрачным идентификатором записи без цели или смысла, кроме как быть уникальной для данной записи в таблице.
Ответ 3
Просто обновление для Andrew great answer (извините, у меня недостаточно репутации для добавления в качестве комментария), теперь поддержка вызова #default_scope без блока теперь удалена. В настоящее время допустимый синтаксис в модели:
default_scope { sort(id: 'ASC') }
Ответ 4
Вы должны явно заказать ваши запросы. Как правило, нет гарантированного или фиксированного заказа, предоставляемого базой данных.
Кроме того, вы не должны использовать 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)
Ответ 5
Хорошо, для моей записи мои тесты дали следующее объяснение: на PostgreSQL (и, возможно, на других) метод "все", как представляется, возвращает вещи в порядке их последнего сохранения (см. комментарий ниже). Таким образом, последний сохраненный элемент возвращает последний, и сначала сохраняется самый старый сохраненный элемент. Я смог "исправить" заказ, оставив все модели в порядке идентификаторов.
Эта проблема не существует в SQLite и т.д., но ответ Стива имеет смысл (нет гарантии, что записи вернутся в определенном порядке). Кроме того, ответ Эндрю Маршалла работает.