pymongo error when writing

2020-06-12 06:29发布

问题:

I am unable to do any writes to a remote mongodb database. I am able to connect and do lookups (e.g. find). I connect like this:

conn = pymongo.MongoClient(db_uri,slaveOK=True)
db = conn.test_database
coll = db.test_collection

But when I try to insert,

coll.insert({'a':1})

I run into an error:

---------------------------------------------------------------------------
AutoReconnect                             Traceback (most recent call last)
<ipython-input-56-d4ffb9e3fa79> in <module>()
----> 1 coll.insert({'a':1})

/usr/lib/python2.7/dist-packages/pymongo/collection.pyc in insert(self, doc_or_docs, manipulate, safe, check_keys, continue_on_error, **kwargs)
    410             message._do_batched_insert(self.__full_name, gen(), check_keys,
    411                                        safe, options, continue_on_error,
--> 412                                        self.uuid_subtype, client)
    413 
    414         if return_one:

/usr/lib/python2.7/dist-packages/pymongo/mongo_client.pyc in _send_message(self, message, with_last_error, command, check_primary)
   1126             except (ConnectionFailure, socket.error), e:
   1127                 self.disconnect()
-> 1128                 raise AutoReconnect(str(e))
   1129             except:
   1130                 sock_info.close()

AutoReconnect: not master

If I remove the slaveOK=True (setting it to it's default value of False) then I can still connect, but the reads (and writes) fail:

AutoReconnect                             Traceback (most recent call last)
<ipython-input-70-6671eea24f80> in <module>()
----> 1 coll.find_one()

/usr/lib/python2.7/dist-packages/pymongo/collection.pyc in find_one(self, spec_or_id, *args, **kwargs)
    719                            *args, **kwargs).max_time_ms(max_time_ms)
    720 
--> 721         for result in cursor.limit(-1):
    722             return result
    723         return None

/usr/lib/python2.7/dist-packages/pymongo/cursor.pyc in next(self)
   1036             raise StopIteration
   1037         db = self.__collection.database
-> 1038         if len(self.__data) or self._refresh():
   1039             if self.__manipulate:
   1040                 return db._fix_outgoing(self.__data.popleft(),

/usr/lib/python2.7/dist-packages/pymongo/cursor.pyc in _refresh(self)
    980                               self.__skip, ntoreturn,
    981                               self.__query_spec(), self.__fields,
--> 982                               self.__uuid_subtype))
    983             if not self.__id:
    984                 self.__killed = True

/usr/lib/python2.7/dist-packages/pymongo/cursor.pyc in __send_message(self, message)
    923                                                 self.__tz_aware,
    924                                                 self.__uuid_subtype,
--> 925                                                 self.__compile_re)
    926         except CursorNotFound:
    927             self.__killed = True

/usr/lib/python2.7/dist-packages/pymongo/helpers.pyc in _unpack_response(response, cursor_id, as_class, tz_aware, uuid_subtype, compile_re)
     99         error_object = bson.BSON(response[20:]).decode()
    100         if error_object["$err"].startswith("not master"):
--> 101             raise AutoReconnect(error_object["$err"])
    102         elif error_object.get("code") == 50:
    103             raise ExecutionTimeout(error_object.get("$err"),

AutoReconnect: not master and slaveOk=false

Am I connecting incorrectly? Is there a way to specify connecting to the primary replica?

回答1:

AutoReconnect: not master means that your operation is failing because the node on which you are attempting to issue the command is not the primary of a replica set, where the command (e.g., a write operation) requires that node to be a primary. Setting slaveOK=True just enables you to read from a secondary node, where by default you would only be able to read from the primary.

MongoClient is automatically able to discover and connect to the primary if the replica set name is provided to the constructor with replicaSet=<replica set name>. See "Connecting to a Replica Set" in the PyMongo docs.

As an aside, slaveOK is deprecated, replaced by ReadPreference. You can specify a ReadPreference when creating the client or when issuing queries, if you want to target a node other than the primary.