Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-38621

Regex $options is ignored when it appears before a $regex BSON regular expression

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.1.9
    • Component/s: Querying
    • Labels:
    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Sprint:
      Query 2019-01-14, Query 2019-02-11, Query 2019-02-25

      Description

      When both $options and $regex are BSON strings the order they appear in the query does not seem to matter. However $options appears to be ignored when it appears first and $regex is a BSON regular expression.

      import pymongo
      import re
      from bson import SON
       
      client = pymongo.MongoClient()
      coll = client.test.test
       
      coll.drop()
      coll.insert_one({'array': [re.compile(b'62', 0), 'no options']})
      coll.insert_one({'array': [re.compile(b'62', re.IGNORECASE), 'IGNORECASE']})
       
      for q in [
              {'array': SON([('$options', 'i'), ('$regex', '62')])},
              {'array': SON([('$regex', '62'), ('$options', 'i')])},
              {'array': SON([('$regex', re.compile(b'62', re.IGNORECASE))])},
              {'array': SON([('$regex', re.compile(b'62')), ('$options', 'i')])},
              {'array': SON([('$options', 'i'), ('$regex', re.compile(b'62'))])}]:
          res = list(coll.find(q, projection={'_id': False}))
          print('>>> list(coll.find(%r)):\n%r' % (q, res))
      

      Expected output:

      >>> list(coll.find({'array': SON([('$options', 'i'), ('$regex', '62')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', '62'), ('$options', 'i')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', re.compile(b'62', re.IGNORECASE))])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', re.compile(b'62')), ('$options', 'i')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$options', 'i'), ('$regex', re.compile(b'62'))])})):
      [{'array': [Regex('62', 0), 'IGNORECASE']}]
      

      Actual output (notice the difference in the final query):

      >>> list(coll.find({'array': SON([('$options', 'i'), ('$regex', '62')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', '62'), ('$options', 'i')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', re.compile(b'62', re.IGNORECASE))])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$regex', re.compile(b'62')), ('$options', 'i')])})):
      [{'array': [Regex('62', 2), 'IGNORECASE']}]
      >>> list(coll.find({'array': SON([('$options', 'i'), ('$regex', re.compile(b'62'))])})):
      [{'array': [Regex('62', 0), 'no options']}]
      

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                8 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: