问题
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