Closed niels closed 11 years ago
This is already implemented here: https://github.com/mongoid/origin/blob/master/lib/origin/optional.rb#L235, isn't?
No, it isn't. Using .without
overwrites the field selection previously set by .only
, whereas it should append (at least in the special case of wanting to exclude only the id):
1.9.3p286 :043 > User.only(:facebook_id) # Correct
=> #<Mongoid::Criteria
selector: {},
options: {:fields=>{"facebook_id"=>1}},
class: User,
embedded: false>
1.9.3p286 :044 > User.without(:_id) # Correct
=> #<Mongoid::Criteria
selector: {},
options: {:fields=>{"_id"=>0}},
class: User,
embedded: false>
1.9.3p286 :045 > User.only(:facebook_id).without(:_id) # Incorrectly overwritten
=> #<Mongoid::Criteria
selector: {},
options: {:fields=>{"_id"=>0}},
class: User,
embedded: false>
1.9.3p286 :045 > User.only(:facebook_id).without(:_id) # Expected
=> #<Mongoid::Criteria
selector: {},
options: {:fields=>{"facebook_id"=>1, "_id"=>0}},
class: User,
embedded: false>
While mixing of field in- and exclusion is generally not allowed, one can explicitly exclude the _id field when providing a list of other fields to include. This is desirable when wanting to execute a query that is completely covered by an index which does not include the id field. In these cases, it must explicitly be excluded from the query.
A real-world use case: We have many users, some of which may have registered with their facebook account. We have an index on _id and a sparse index on facebook_id. We do not want to include _id in the latter in order to keep index size down. To quickly gather up all facebook_ids, we want to execute a covered query against the facebook_id index.
Current implementation: User.only(:facebook_id).tap { |q| q.options[:fields][:_id] = 0 }
Desired implementation: User.only(:facebook_id).without(:_id)