Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-459

Changes to Cursor.clone() in 2.4 break $hint.

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.4.2
    • Affects Version/s: 2.4, 2.4.1
    • Component/s: None
    • Labels:
      None

      When subscript notation is used on a cursor object to get a specific document from the cursor a clone of the original cursor is made. Changes to clone in 2.4 break operations that require an ordered dictionary. The best example is when using $hint:

      >>> import pymongo
      >>> c = pymongo.MongoClient()
      >>> hint = [(u'uid', 1), (u'service', 1), (u'site_path', 1), (u'url_path', 1), (u'status', 1)]
      >>> cur = c.test.post.find( { "site_path": "/ued/", "status": "public", "url_path": "thinking/wo-wei-shi-yao-tao-yanpm", "uid": 4919465, "service": "dropbox" }).hint(hint)
      >>> cur.next()
      {u'site_path': u'/ued/', u'status': u'public', u'url_path': u'thinking/wo-wei-shi-yao-tao-yanpm', u'uid': 4919465.0, u'service': u'dropbox', u'_id': ObjectId('50e87075deaf17f2dc7632cb')}
      >>> cur = c.test.post.find( { "site_path": "/ued/", "status": "public", "url_path": "thinking/wo-wei-shi-yao-tao-yanpm", "uid": 4919465, "service": "dropbox" }).hint(hint)
      >>> cur[0]
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "pymongo/cursor.py", line 470, in __getitem__
          for doc in clone:
        File "pymongo/cursor.py", line 814, in next
          if len(self.__data) or self._refresh():
        File "pymongo/cursor.py", line 763, in _refresh
          self.__uuid_subtype))
        File "pymongo/cursor.py", line 720, in __send_message
          self.__uuid_subtype)
        File "pymongo/helpers.py", line 105, in _unpack_response
          error_object["$err"])
      pymongo.errors.OperationFailure: database error: bad hint
      

      Notice the second operation does cur[0] instead of cur.next(), creating a clone of the original cursor. The clone operation seems to replace the SON instance with a regular dictionary, changing the index hint order:

      >>> cur = c.test.post.find( { "site_path": "/ued/", "status": "public", "url_path": "thinking/wo-wei-shi-yao-tao-yanpm", "uid": 4919465, "service": "dropbox" }).hint(hint)
      >>>
      >>> cur._Cursor__hint
      SON([(u'uid', 1), (u'service', 1), (u'site_path', 1), (u'url_path', 1), (u'status', 1)])
      >>>
      >>> cln = cur._Cursor__clone()
      >>> cln._Cursor__hint
      {u'site_path': 1, u'status': 1, u'url_path': 1, u'uid': 1, u'service': 1}
      

            Assignee:
            ross@mongodb.com Ross Lawley
            Reporter:
            bernie@mongodb.com Bernie Hackett
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: