[SERVER-15696] $regex, $in and $sort with index returns too many results Created: 16/Oct/14 Updated: 11/Jul/16 Resolved: 04/Nov/14 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Querying |
| Affects Version/s: | 2.6.4, 2.6.5, 2.7.7 |
| Fix Version/s: | 2.6.6, 2.8.0-rc0 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Simon Lavigne-Giroux | Assignee: | David Storch |
| Resolution: | Done | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Operating System: | ALL | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Backport Completed: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Steps To Reproduce: | My index is :
Here's a working query hinting not to use the index which returns 2 results :
Using the index, it returns 62 elements because it discards the searchField $regex filter.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Participants: |
| Description |
|
The combination of a $regex, $in and $sort using an index returns too many results. The sort is done on the field filtered with a $regex and that filter is completely discarded. We get 62 results with the index and 2 results without it. |
| Comments |
| Comment by Githook User [ 18/Nov/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}Message: (cherry picked from commit dcb68b25fe7351888385cc435f339ada8e8b5e9e) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Githook User [ 04/Nov/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}Message: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 20/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It's a single query with multiple $or clauses, so you only run a single query still.
See my alternate working solution if you can avoid case insensitive options to $regex then wrapping regex _dr and regex _DR in an $or also works. That doesn't require creating a second field with identical value. Asya | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Nicolas [ 20/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I mean that we would need to repeat regex query X times instead of writing it down only once. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 20/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I'm not sure what you mean by "really big" and "for nothing" is relative. Your other options would be to replace the index with one on just channelId and have mongod do in memory sort (if result set expected is not huge that might be okay). Another work-around (if you only care about matching "_dr" and "_DR" (as far as using case insensitive regex) would be to use this syntax:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by David Storch [ 20/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I can reproduce the issue with this simple script:
Explaining the query against a 2.7.7 server shows that the $regex filter is being discarded:
The problem is that the stage labeled SORT_MERGE is not filtering the results according to the regular expression. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Nicolas [ 20/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yeah, but the problem is that we can have a LOT of channelIds. It would make the query REALLY big for nothing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 18/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ironically, the performance should be better (the index will be used properly then - I think the bug may in how it decides the index should apply to original query which ought to be identical to re-written query but isn't). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Simon Lavigne-Giroux [ 18/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Are the performance going to be the same? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 18/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Possible workaround: Transforming the query:
into
returns the correct results. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Simon Lavigne-Giroux [ 18/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yes that was my observation as well. They are all necessary to trigger the incorrect behavior. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 18/Oct/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thank you for reporting the problem and for the detailed reproducer. We have been able to confirm this bug - it seems that the $in clause on the leading part of the index and the sort on the second field of the index (and $regex on second field) are all necessary to trigger the incorrect behavior, was that your observation as well? Asya |