I've got a strange issue on a Heroku deployment that I can't seem to duplicate locally. Basically when I find all on a specific model instead of sorting by ID it seems to return them in no order at all.
我在Heroku部署上遇到了一个奇怪的问题,我似乎无法在本地复制。基本上当我在特定模型上找到所有模型而不是按ID排序时,它似乎根本无法返回它们。
Typically the records come out like so:
通常记录如下:
>> Model.all
=> [<model id: 2>,<model id: 1>,<model id: 3>,<model id: 4>,<model id: 5>]
... and so on.
... 等等。
If I explicitly call Model.order("id ASC")
it returns the models as expected.
如果我显式调用Model.order(“id ASC”),它会按预期返回模型。
What gives? Why would find all not return the objects in descending ID order?
是什么赋予了?为什么会发现所有不按ID递减顺序返回对象?
4 个解决方案
#1
25
Ordering by ID is not guaranteed by default, since it’s up to the database how a non-ordered query gets ordered (typically it’s unspecified). You can make it always be ordered by defining a default scope at the top of your model like so:
默认情况下,不保证按ID排序,因为数据库是如何排序非有序查询的(通常是未指定的)。您可以通过在模型顶部定义默认范围来始终对其进行排序,如下所示:
default_scope { order('id ASC') }
Then calling Model.all
will be equivalent to calling Model.order('id ASC')
.
然后调用Model.all将等同于调用Model.order('id ASC')。
#2
8
In SQL, tables are considered to be sets of records, not lists of records, and a 'select' query is not guaranteed to return records in any particular order unless an 'order by' clause is specifically included. You may happen to see that results come back in a particular order sometimes, but that doesn't mean you can or should assume it will always be so.
在SQL中,表被视为记录集,而不是记录列表,并且不保证“选择”查询以任何特定顺序返回记录,除非明确包含“order by”子句。您可能偶尔会看到结果以特定顺序返回,但这并不意味着您可以或应该假设它始终如此。
Using ActiveRecord, you can force a default 'order by' clause if you like by specifying a default scope. In general, that's a bad idea though, because it will force the server to do more work to give you a sorted result set, even when you don't need it sorted. Furthermore, sorting in the 'id' field is usually inappropriate, since the point of 'id' is to be an opaque record identifier with no purpose or meaning other than to be unique for a given record in a table.
使用ActiveRecord,如果您愿意,可以通过指定默认范围来强制使用默认的“order by”子句。一般来说,这是一个坏主意,因为它会强制服务器做更多的工作来为你提供一个排序的结果集,即使你不需要它排序。此外,在'id'字段中排序通常是不合适的,因为'id'的点是不透明的记录标识符,没有任何目的或意义,除了对于表中的给定记录是唯一的。
#3
2
Just a update for Andrew's great answer (sorry I don't have enough reputation to add as a comment), the support for calling #default_scope without a block is now removed. Currently the acceptable syntax in Model is:
只是安德鲁的最佳答案的更新(抱歉,我没有足够的声誉添加评论),现在删除了对没有阻止调用#default_scope的支持。目前Model中可接受的语法是:
default_scope { sort(id: 'ASC') }
#4
0
Ok, for the record my tests yielded the following explanation: on PostgreSQL (and possibly others) the "all" method appears to return things in the order of their last save (see comment below). So, the most recently saved item returns last and the oldest saved item returns first. I was able to "fix" the order by resaving all the models in ID order.
好的,为了记录,我的测试产生了以下解释:在PostgreSQL(以及可能的其他)上,“all”方法似乎按照上次保存的顺序返回事物(请参阅下面的注释)。因此,最近保存的项目最后返回,最早保存的项目首先返回。我能够通过以ID顺序重新保存所有模型来“修复”订单。
This issue does not exist on SQLite etc, but Steve's answer makes sense (there's no guarantee the records will come back in a specific order). Also, Andrew Marshall's answer does work.
这个问题在SQLite等上不存在,但史蒂夫的回答是有道理的(不能保证记录会以特定的顺序返回)。此外,安德鲁马歇尔的答案确实有效。
#1
25
Ordering by ID is not guaranteed by default, since it’s up to the database how a non-ordered query gets ordered (typically it’s unspecified). You can make it always be ordered by defining a default scope at the top of your model like so:
默认情况下,不保证按ID排序,因为数据库是如何排序非有序查询的(通常是未指定的)。您可以通过在模型顶部定义默认范围来始终对其进行排序,如下所示:
default_scope { order('id ASC') }
Then calling Model.all
will be equivalent to calling Model.order('id ASC')
.
然后调用Model.all将等同于调用Model.order('id ASC')。
#2
8
In SQL, tables are considered to be sets of records, not lists of records, and a 'select' query is not guaranteed to return records in any particular order unless an 'order by' clause is specifically included. You may happen to see that results come back in a particular order sometimes, but that doesn't mean you can or should assume it will always be so.
在SQL中,表被视为记录集,而不是记录列表,并且不保证“选择”查询以任何特定顺序返回记录,除非明确包含“order by”子句。您可能偶尔会看到结果以特定顺序返回,但这并不意味着您可以或应该假设它始终如此。
Using ActiveRecord, you can force a default 'order by' clause if you like by specifying a default scope. In general, that's a bad idea though, because it will force the server to do more work to give you a sorted result set, even when you don't need it sorted. Furthermore, sorting in the 'id' field is usually inappropriate, since the point of 'id' is to be an opaque record identifier with no purpose or meaning other than to be unique for a given record in a table.
使用ActiveRecord,如果您愿意,可以通过指定默认范围来强制使用默认的“order by”子句。一般来说,这是一个坏主意,因为它会强制服务器做更多的工作来为你提供一个排序的结果集,即使你不需要它排序。此外,在'id'字段中排序通常是不合适的,因为'id'的点是不透明的记录标识符,没有任何目的或意义,除了对于表中的给定记录是唯一的。
#3
2
Just a update for Andrew's great answer (sorry I don't have enough reputation to add as a comment), the support for calling #default_scope without a block is now removed. Currently the acceptable syntax in Model is:
只是安德鲁的最佳答案的更新(抱歉,我没有足够的声誉添加评论),现在删除了对没有阻止调用#default_scope的支持。目前Model中可接受的语法是:
default_scope { sort(id: 'ASC') }
#4
0
Ok, for the record my tests yielded the following explanation: on PostgreSQL (and possibly others) the "all" method appears to return things in the order of their last save (see comment below). So, the most recently saved item returns last and the oldest saved item returns first. I was able to "fix" the order by resaving all the models in ID order.
好的,为了记录,我的测试产生了以下解释:在PostgreSQL(以及可能的其他)上,“all”方法似乎按照上次保存的顺序返回事物(请参阅下面的注释)。因此,最近保存的项目最后返回,最早保存的项目首先返回。我能够通过以ID顺序重新保存所有模型来“修复”订单。
This issue does not exist on SQLite etc, but Steve's answer makes sense (there's no guarantee the records will come back in a specific order). Also, Andrew Marshall's answer does work.
这个问题在SQLite等上不存在,但史蒂夫的回答是有道理的(不能保证记录会以特定的顺序返回)。此外,安德鲁马歇尔的答案确实有效。