Rails: Calling .limit(5) changes order of results

被刻印的时光 ゝ 提交于 2019-12-11 02:15:00

问题


I have a search function that basically runs an ordered list of model records. The problem is whenever I called .search.limit(5), the results are in a different order from when I call .search

Here is some of my method

    def self.search(server_name, pvp_type)
          if server_name.nil?
            result = Rom::Leaderboard.order('pvp_vs desc, win_percent desc').limit(200) 
          end
    end

When I call

Rom::Leaderboard.search(nil, 2).pluck(:actor_name)

SQL Translation:

SELECT "rom_leaderboards"."actor_name" FROM "rom_leaderboards" WHERE "rom_leaderboards"."pvp_type" = 2 ORDER BY pvp_vs desc, win_percent desc LIMIT 200

I get the following results:

[Zarglon, Lirav, adf, sdfa, Nonad, ...]

Zarglon and Lirav have the same pvp_vs & win_percent attribute values; afd, sdfa, and Nonad also have the same relationship.

Now when I call

Rom::Leaderboard.search(nil, 2).limit(5).pluck(:actor_name)

SQL Translation:

SELECT "rom_leaderboards"."actor_name" FROM "rom_leaderboards" WHERE "rom_leaderboards"."pvp_type" = 2 ORDER BY pvp_vs desc, win_percent desc LIMIT 5

I get the following results:

[Lirav, Zarglon, sfda, Nonad, adf]

These queries are both correct (since search returns a ordered list based on pvp_vs & win_percent and both list are ordered correctly). But I want them to be the same. For some reason limit changes this order. Is there anyway to keep them the same?


回答1:


Suppose you try to order this array-of-arrays by the first element:

[
  [ 1, 1 ],
  [ 1, 2 ],
  [ 1, 3 ]
]

Both of these (and several others) are valid results because you have duplicate sort keys:

[ [1,1], [1,2], [1,3] ]
[ [1,3], [1,1], [1,2] ]

You're encountering the same problem inside the database. You say that:

Zarglon and Lirav have the same pvp_vs & win_percent attribute values; afd, sdfa, and Nonad also have the same relationship.

So those five values can appear in any order and still satisfy your specified ORDER BY condition. They don't even have to come out of the database in the same order in two executions of the same query.

If you want consistent ordering, you need to ensure that each row in your result set has a unique sort key so that ties will be broken consistently. This is ActiveRecord so you'll have a unique id available so you can use that to break your ordering ties:

result = Rom::Leaderboard.order('pvp_vs desc, win_percent desc, id').limit(200) 
# --------------------------------------------------------------^^

That will give you a well defined and unique ordering.



来源:https://stackoverflow.com/questions/19303998/rails-calling-limit5-changes-order-of-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!