Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-2797

Forward find conditions to View#aggregate

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Minor - P4 Minor - P4
    • 2.18.0
    • Affects Version/s: None
    • Component/s: None
    • None
    • Fully Compatible

      When aggregate method is called on a view, i.e.

      collection.find({}).aggregate
      

      ... if any conditions are passed to find, these conditions will not be utilized by the aggregate method.

      This behavior can be surprising to users and should be documented.

      We could potentially pass the conditions by wrapping them into a $match stage, however this likely would violate the "no helpers" driver mantra.

      Currently the reference documentation only describes Collection#aggregate method and does not document View#aggregate at all, thus there is no existing place in our reference documentation to add this caveat to. This ticket is to document this situation; if any behavior changes are made, likely they should be done as part of https://jira.mongodb.org/browse/RUBY-2706.


      Original report:

      The current implementation of mongo v1.15 :find public_methods shows that :aggregate can be run, implying that an aggregate() ran on a preceding find() would be bound by the find()'s search parameters.

      client = Mongo::Client.new
      col = 'test'
      client[col].find.methods.grep(/aggregate/)
      => [:aggregate]
      

      For example, assuming a collection of 50 records, half of which have a boolean value of { find_me: true }.

      irb(main):> (1..25).each { |i| client[col].insert_one({}) }
      => 1..25
      irb(main):> (1..25).each { |i| client[col].insert_one({ find_me: true }) }
      => 1..25
      irb(main):> client[col].count
      => 50
      irb(main):> client[col].find({ find_me: true }).count
      => 25

      Since we can run an aggregate() on the above find() cursor, I assumed that that aggregate pipeline would be bound by the above search of { find_me: true } with 25 documents and therefor not require a { $match } stage. But that does not appear to be the case:

      irb(main):> client[col].find({ find_me: true }).aggregate([]).count
      => 50
      

      This shows the find() should just be excluded as it is completely ignored by the follow-up aggregate().

      Since this issue was found in only one place of my code where I patched an existing find() with a follow-up aggregate(), assuming the aggregate() would only apply to the find()'s returned documents, I will resolve my own code's bug by removing the find() and just running an aggregate() with the needed { $match } stage.

      My point in opening this bug is that since an aggregate() can be ran on a find(), it can give the false assumption that the aggregate() assumes the preceding find()'s returned documents (25). But instead, it entirely ignores the preceding find()'s returned docs and runs on the full collection's documents (50).

      Perhaps :aggregate should not be an available method of :find within the Ruby Mongo driver.

       

       

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            danheneise@me.com Dan Heneise
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: