Skip to content

MONGOID-5098 Standardize/improve Range queries -- .where(field: 1..3) #5025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 29, 2021

Conversation

johnnyshields
Copy link
Contributor

@johnnyshields johnnyshields commented Aug 10, 2021

Behavior changes:

  • Non-inclusive ranges 1...3 should use $lt operator.
    • Example: 1...3 should be $gte: 1, $lt: 3. Currently it does $gte: 1, $lte: 2 which will not query Floats correctly.
  • Support beginning-less ..1 / ...1 and endless 1.. ranges, if Ruby version supports them.
  • Make __evolve__ handling consistent across various methods, including consistent handling of Date/Time/TimeWithZone

Lastly, I considered supporting descending ranges such as 3..1 but I've held off on it for now since they basically don't work in Ruby (3..1).cover?(2) => false. I do think it would be nice-to-have however and I have the code for it so if desirable I can raise it as a follow-up PR.

Fixes half of MONGOID-5098

Related to MONGOID-5026 but can be merged independently

- Non-inclusive ranges 1...3 should use $lt operator
- Support beginning-less ..1 / ...1 and endless 1.. ranges
- Make __evolve__ handling consistent across various methods
@johnnyshields johnnyshields changed the title Improve range queries Improve Range queries -- .where(1..3) Aug 11, 2021
@johnnyshields johnnyshields changed the title Improve Range queries -- .where(1..3) Improve Range queries -- .where(field: 1..3) Aug 11, 2021
@johnnyshields johnnyshields changed the title Improve Range queries -- .where(field: 1..3) Standardize/improve Range queries -- .where(field: 1..3) Aug 11, 2021
@johnnyshields johnnyshields changed the title Standardize/improve Range queries -- .where(field: 1..3) MONGOID-5098 Standardize/improve Range queries -- .where(field: 1..3) Aug 11, 2021
johnnyshields and others added 3 commits August 25, 2021 12:59
* master: (26 commits)
  MONGOID-5128 Scoped associations (mongodb#5017)
  MONGOID-5005 - .sum, .count, and similar aggregables now ignore sort if not limiting/skipping (mongodb#5049)
  MONGOID-5098 Improve specs for timezone handling (specs only; no behavior change) (mongodb#5023)
  MONGOID-5151 Respect aliased fields in pluck/distinct by having Document.database_field_name recursively consider embedded docs (mongodb#5047)
  RUBY-2675 test coverage on the Mongoid side (mongodb#5030)
  MONGOID-4592 Add examples of using read_attribute and write_attribute to implement custom field behavior (mongodb#5082)
  MONGOId-5185 Remove tests for _id serialization (mongodb#5081)
  MONGOID-5103 Implement eq symbol operator (mongodb#5076)
  Fix MONGOID-5006 Link default auth source documentation to driver instead of incorrectly claiming "admin" is always the default (mongodb#5048)
  Create security policy following github's template (mongodb#5070)
  MONGOID-5131 Use proper mdb <-> ubuntu versions (mongodb#5067)
  MONGOID-5131: Set up build pipeline for outside contributors (mongodb#5043)
  MONGOID-5165 Fix documentation link (mongodb#5065)
  Fix indentation
  MONGOID-5029 #empty method should use an #exists? rather than a #count query (mongodb#5029)
  MONGOID-5177 Fix flaky contextual spec (mongodb#5064)
  MONGOID-5170 - Fix more typos mostly in code docs and code comments (mongodb#5056)
  MONGOID-5105 Allow block form in Mongoid::Association::EmbedsMany::Proxy#count  (mongodb#5060)
  MONGOID-5162 Add a release note for the planned changes in ObjectId#as_json (mongodb#5059)
  MONGOID-5171 - Make the minimum Ruby version 2.5 (mongodb#5058)
  ...
@johnnyshields
Copy link
Contributor Author

@p-mongo __evolve_range_naive__ always returns a new Hash. Therefore it's safe (and better performance) to mutate the object.

@p-mongo
Copy link
Contributor

p-mongo commented Sep 23, 2021

It is true that the current implementation returns a new object every time, but this isn't stated in e.g. a docstring as a requirement for the method, therefore it is possible that at a future time someone might alter it to have different behavior. Looking at it again, given that it is a private method, I think it would be safe to mutate its value if it's given @api private annotation and the docstring explicitly said that a new object must be returned each time because it will be mutated.

@johnnyshields
Copy link
Contributor Author

johnnyshields commented Sep 23, 2021

Since the method itself is private, it should be fine.

AFAIK @api private only used on public methods to declare that they should not be considered part of the public-facing API (even though they are in fact public.) Flagging a private method as @api private is redundant.

@p-mongo
Copy link
Contributor

p-mongo commented Sep 24, 2021

Unfortunately when methods are defined in modules which are included in user code (e.g. Mongoid::Document) there can be confusion as to whether a method is private to Mongoid or it is private to the class (but is usable by other methods of the same class). For this reason Mongoid frequently contains @api private annotations on private-visibility methods.

@johnnyshields
Copy link
Contributor Author

johnnyshields commented Sep 24, 2021

In your most recent commit:

  context 'endless range' do
    ruby_version_gte '2.7'

    it 'Range<Integer> criteria vs Integer field' do
      expect(Band.where(likes: eval('..3')).to_a).to eq [band1, band2, band3, band4]
      expect(Band.where(likes: eval('...3')).to_a).to eq [band1, band2, band3]

These are actually "beginning-less" ranges.

Note that:

1.. --> works on Ruby 2.6+

..1 --> works on Ruby 2.7+

@p-mongo
Copy link
Contributor

p-mongo commented Sep 24, 2021

@johnnyshields Thanks for pointing that out, I suspected that some syntax was OK for 2.6 but I just wanted to make this PR mergeable and I didn't spend time investigating. I understand that on Ruby 2.6 it is possible to test some of the combinations, if you would like to adjust the tests so that they do that please go ahead.

Another aspect of this PR that I decided to leave as is is the context/it descriptions. In the example you quoted, Range<Integer> criteria vs Integer field should be a context, and it should refer to the behavior (sometimes I cheat and use phrasing like it "works as expected" when there is only one case).

Between these two changes there would be a bit more work in the test files to get them to be 100%, I opted to skip it so that I can move on to your other PRs but if you wish to make these adjustments I will appreciate it.

@p-mongo p-mongo requested a review from comandeo September 24, 2021 11:33
@johnnyshields
Copy link
Contributor Author

@p-mongo I've updated the specs to use context and use Ruby 2.6 vs 2.7 correctly.

@p-mongo p-mongo requested review from comandeo and removed request for comandeo September 28, 2021 14:43
@p-mongo p-mongo merged commit 2238cb7 into mongodb:master Sep 29, 2021
p-mongo pushed a commit to p-mongo/mongoid that referenced this pull request Oct 4, 2021
…mongodb#5025)

* Improve range queries:
- Non-inclusive ranges 1...3 should use $lt operator
- Support beginning-less ..1 / ...1 and endless 1.. ranges
- Make __evolve__ handling consistent across various methods

* Update range.rb

* avoid mutating objects

* fix tests to not produce syntax errors on ruby 2.5

* Revert "avoid mutating objects"

This reverts commit dd90920.

* add mutation note

* 2.6 does not understand one-sided ranges either

* Fix specs

* Whitespace

Co-authored-by: shields <shields@tablecheck.com>
Co-authored-by: Oleg Pudeyev <code@olegp.name>
p-mongo pushed a commit to johnnyshields/mongoid that referenced this pull request Oct 5, 2021
* master:
  Remove remaining encoding declarations (mongodb#5088)
  Add a more descriptive error when spec load fails (mongodb#5066)
  MONGOID-5191 Proper order for after_create callback (mongodb#5087)
  MONGOID-5189 Proper order of *_save callbacks (mongodb#5083)
  MONGOID-5098 Standardize/improve Range queries -- .where(field: 1..3) (mongodb#5025)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants