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

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.1.9
    • Affects Version/s: None
    • Component/s: Querying
    • Fully Compatible
    • ALL
    • Query 2019-01-14, Query 2019-02-11, Query 2019-02-25

      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']}]
      

            Assignee:
            evan.nixon@mongodb.com Evan Nixon
            Reporter:
            shane.harvey@mongodb.com Shane Harvey
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: