[CXX-1001] mongocxx::cursor.begin() increments the iterator Created: 21/Aug/16 Updated: 10/May/17 Resolved: 15/Nov/16 |
|
| Status: | Closed |
| Project: | C++ Driver |
| Component/s: | API |
| Affects Version/s: | 3.0.1 |
| Fix Version/s: | 3.1.0 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | George Thompson | Assignee: | David Golden |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Windows 10 |
||
| Issue Links: |
|
||||||||||||||||||||
| Description |
|
Simple program to create and print out two records:
Output (as expected):
Now, if I insert into the code cursor.begin(); right after the find():
Then my output is (unexpectedly missing the "George" entry):
My objective was to test if the cursor was empty (there is no .empty()) so I tried to use: if ( cursor.begin() == cursor.end() ) but that seemingly advances the iterator? |
| Comments |
| Comment by Githook User [ 29/Nov/16 ] | |||||||||||||||||||
|
Author: {u'username': u'xdg', u'name': u'David Golden', u'email': u'xdg@xdg.me'}Message:
The changes above required some additional coordination to track cursors | |||||||||||||||||||
| Comment by Githook User [ 29/Nov/16 ] | |||||||||||||||||||
|
Author: {u'username': u'xdg', u'name': u'David Golden', u'email': u'xdg@xdg.me'}Message:
The changes above required some additional coordination to track cursors | |||||||||||||||||||
| Comment by Githook User [ 15/Nov/16 ] | |||||||||||||||||||
|
Author: {u'username': u'xdg', u'name': u'David Golden', u'email': u'xdg@xdg.me'}Message:
The changes above required some additional coordination to track cursors | |||||||||||||||||||
| Comment by Githook User [ 15/Nov/16 ] | |||||||||||||||||||
|
Author: {u'username': u'xdg', u'name': u'David Golden', u'email': u'xdg@xdg.me'}Message:
The changes above required some additional coordination to track cursors | |||||||||||||||||||
| Comment by David Golden [ 09/Nov/16 ] | |||||||||||||||||||
| Comment by David Golden [ 24/Oct/16 ] | |||||||||||||||||||
|
Solving this problem must be done in concert with solving | |||||||||||||||||||
| Comment by Mira Carey [ 22/Aug/16 ] | |||||||||||||||||||
|
I don't think it matters much that our cursor's return input iterators instead of forward iterators. Anyone who's trying to enforce the concept is going to care about more than just the presence of begin or end and should care about the iterator tag type. I do think we should cache the last result we read from the libmongoc cursor. If we keep around the last result we read off that cursor, we can make the first call to begin() run the query (so you can tell if there are any results), then successive calls without an iterator advancement return whatever the last result was. That makes our iterators at least InputIterators, and leaves our cursors as non-Container things that happen to have begin and end. | |||||||||||||||||||
| Comment by George Thompson [ 22/Aug/16 ] | |||||||||||||||||||
|
Thanks rassi. | |||||||||||||||||||
| Comment by J Rassi [ 22/Aug/16 ] | |||||||||||||||||||
|
therefore, you could consider buffering the results of the query before checking if the result set is empty, as an alternative workaround:
Or, just use a bool:
| |||||||||||||||||||
| Comment by David Golden [ 22/Aug/16 ] | |||||||||||||||||||
|
I believe you can put $max and $min directly into the filter, but I admit I haven't tried it. | |||||||||||||||||||
| Comment by George Thompson [ 22/Aug/16 ] | |||||||||||||||||||
|
The problem with the .count() workaround is the lack of meta modifiers in mongocxx::options::count which I have available with mongocxx::options::find::modifiers. Specifically in my actual code, I am using $max and $min in my find() which I am unsure I can use with mongocxx::collection::count. Unless mongocxx::options::find::modifiers is a convenience wrapper and I could alternatively implement the modifiers in my bsoncxx::document::view_or_value count filter? | |||||||||||||||||||
| Comment by George Thompson [ 22/Aug/16 ] | |||||||||||||||||||
|
Thank you. | |||||||||||||||||||
| Comment by David Golden [ 22/Aug/16 ] | |||||||||||||||||||
|
For your workaround, I'd suggest issuing a count with a limit of 1 to test if you'll get any documents. That at least minimizes the expense. Then issue your find command if there are. There's a race condition, but it's no different than if you issued a find instead of a count and it found no documents either. | |||||||||||||||||||
| Comment by George Thompson [ 22/Aug/16 ] | |||||||||||||||||||
|
Thanks david.golden. I am always hesitant to mark questions as a bug. When I stepped into the mongoDB code, it did appear to increment which isn't (I believe) standard behavior for an STL input iterator (or any iterator). Is the only workaround to re-issue the query? I am currently in development so I can do that (expensive) temporary workaround for now. | |||||||||||||||||||
| Comment by David Golden [ 22/Aug/16 ] | |||||||||||||||||||
|
I agree it's unusual. The iterator is an input iterator and begin really only makes sense for a forward iterator. But "rewinding" a cursor means re-issuing a query to MongoDB, which is expensive. I'm going to mark this as a bug and update the title and we'll work on a solution for your use case. Thank you for reporting this! | |||||||||||||||||||
| Comment by George Thompson [ 22/Aug/16 ] | |||||||||||||||||||
|
Thanks david.golden. But that means:
fails. I.e., there will be no output since the cursor has incremented. Should I decrement the cursor in case begin() and end() are not equal? Is this not unique behavior for a cursor? | |||||||||||||||||||
| Comment by David Golden [ 22/Aug/16 ] | |||||||||||||||||||
|
The iterator is a view on the cursor rather than being independent, so cursor.begin() currently gets a view on the first document and (behind the scenes) the cursor gets incremented to be ready for the next one. However, cursor.begin() will still equal cursor.end() for an empty cursor. |