I’m storing day numbers 0-6 in an array on a document.
I want the documents to always be in the correct order but sunday(0) is making that troublesome since it will be before monday(1). How could I make this ordering in another way?
default_scope asc(:days)
Update:
So when trying to implement a custom serialization I ran into a problem:
class Schedule
include Mongoid::Document
field :days, type: Days
default_scope order_by([[:days, :asc]])
end
class Days
include Mongoid::Fields::Serializable
# Convert Ruby wday format, sunday(0) - saturday(6).
def deserialize(days)
days.map { |day| (day + 1)%7 }
end
# Convert to MongoDB friendly format, monday(0) - sunday(6).
def serialize(days)
days.map { |day| (day + 6)%7 }
end
end
So far so good, the custom field serialization works as expected:
s2 = Schedule.create(days: [0])
s.days
# Deserialized value => [0]
s.read_attribute :days
# Stored value => [6]
However, Mongoid seems to sort on the deserialized object?
s2 = Schedule.create(days: [1,2,3,4,5])
s2.days
# Deserialized value => [1, 2, 3, 4, 5]
s2.read_attribute :days
# Stored value => [0, 1, 2, 3, 4]
Schedule.all
# Sorted as => [s1, s2]
# Expected sort order => [s2, s1]
Confirmed by removing the deserialization, that will return the documents in the correct order. It might be worth noting that this is an embedded document, I guess maybe the ordering is done in a different way.
Update 2:
I ended up creating a second field, sortable_days, which I used the serializer on, but not the deserializer, and then sorted on that field instead.
MongoDB only allows sorting on a field for forward/reverse values. By using 0 for sunday, there’s no way to preserve the ordering for 1-6 but put 0 at the end. In Postgres or other SQL servers you could use a custom sort function to achieve this, but there is no analogue in MongoDB.
You will need to change your value encoding for this. You could create a denormalize version of this value that has the transformed (0 => 7) value for this field and sort on this field.