mongodbazureazure-cosmosdbpymongoazure-cosmosdb-mongoapi

PyMongo on Azure Cosmos and MongoDB


I created an Azure Cosmos (RU) Serverless database (sharded) with a MongoDB engine and would like to use Python and pymongo to run queries on it. I am not managing to connect to it in any way. I have tested both version 3.6 and version 7.0 of the Mongo DB Server.

enter image description here

The connection string I use has this format:

mongodb://{user_name}:{primary_key}@{service_name}.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@{service_name}@

I tried different versions of pymongo, but no luck. Tested on different networks (no firewall connectivity problems).

Also, with azure-cosmos the connection works, but it cannot be used for nosql engines.

The code I use is as follows. It goes into a timeout:

import pymongo

CONN_STRING = “mongodb://etc....”

client = pymongo.MongoClient(CONN_STRING)

client.list_database_names()

Error:

{
    "name": "ServerSelectionTimeoutError",
    "message": "{service_name}.mongo.cosmos.azure.com:10255: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6734b32d878003e1a30f46fb, topology_type: Single, servers: [<ServerDescription ('{service_name}.mongo.cosmos.azure.com', 10255) server_type: Unknown, rtt: None, error=NetworkTimeout('{service_name}.mongo.cosmos.azure.com:10255: timed out')>]>",
    "stack": "---------------------------------------------------------------------------
ServerSelectionTimeoutError               Traceback (most recent call last)
Cell In[17], line 1
----> 1 client.list_database_names()

File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1918, in MongoClient.list_database_names(self, session)
   1908 def list_database_names(self, session=None):
   1909     \"\"\"Get a list of the names of all databases on the connected server.
   1910 
   1911     :Parameters:
   (...)
   1915     .. versionadded:: 3.6
   1916     \"\"\"
   1917     return [doc[\"name\"]
-> 1918             for doc in self.list_databases(session, nameOnly=True)]

File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1899, in MongoClient.list_databases(self, session, **kwargs)
   1897 cmd.update(kwargs)
   1898 admin = self._database_default_options(\"admin\")
-> 1899 res = admin._retryable_read_command(cmd, session=session)
   1900 # listDatabases doesn't return a cursor (yet). Fake one.
   1901 cursor = {
   1902     \"id\": 0,
   1903     \"firstBatch\": res[\"databases\"],
   1904     \"ns\": \"admin.$cmd\",
   1905 }

File ...\\Lib\\site-packages\\pymongo\\database.py:755, in Database._retryable_read_command(self, command, value, check, allowable_errors, read_preference, codec_options, session, **kwargs)
    750 def _cmd(session, server, sock_info, slave_ok):
    751     return self._command(sock_info, command, slave_ok, value,
    752                          check, allowable_errors, read_preference,
    753                          codec_options, session=session, **kwargs)
--> 755 return self.__client._retryable_read(
    756     _cmd, read_preference, session)

File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1460, in MongoClient._retryable_read(self, func, read_pref, session, address, retryable, exhaust)
   1458 while True:
   1459     try:
-> 1460         server = self._select_server(
   1461             read_pref, session, address=address)
   1462         if not server.description.retryable_reads_supported:
   1463             retryable = False

File ...\\Lib\\site-packages\\pymongo\\mongo_client.py:1278, in MongoClient._select_server(self, server_selector, session, address)
   1275         raise AutoReconnect('server %s:%d no longer available'
   1276                             % address)
   1277 else:
-> 1278     server = topology.select_server(server_selector)
   1279     # Pin this session to the selected server if it's performing a
   1280     # sharded transaction.
   1281     if server.description.mongos and (session and
   1282                                       session.in_transaction):

File ...\\Lib\\site-packages\\pymongo\\topology.py:241, in Topology.select_server(self, selector, server_selection_timeout, address)
    236 def select_server(self,
    237                   selector,
    238                   server_selection_timeout=None,
    239                   address=None):
    240     \"\"\"Like select_servers, but choose a random server if several match.\"\"\"
--> 241     return random.choice(self.select_servers(selector,
    242                                              server_selection_timeout,
    243                                              address))

File ...\\Lib\\site-packages\\pymongo\\topology.py:199, in Topology.select_servers(self, selector, server_selection_timeout, address)
    196     server_timeout = server_selection_timeout
    198 with self._lock:
--> 199     server_descriptions = self._select_servers_loop(
    200         selector, server_timeout, address)
    202     return [self.get_server_by_address(sd.address)
    203             for sd in server_descriptions]

File ...\\Lib\\site-packages\\pymongo\\topology.py:215, in Topology._select_servers_loop(self, selector, timeout, address)
    212 while not server_descriptions:
    213     # No suitable servers.
    214     if timeout == 0 or now > end_time:
--> 215         raise ServerSelectionTimeoutError(
    216             \"%s, Timeout: %ss, Topology Description: %r\" %
    217             (self._error_message(selector), timeout, self.description))
    219     self._ensure_opened()
    220     self._request_check_all()

ServerSelectionTimeoutError: {service_name}.mongo.cosmos.azure.com:10255: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6734b32d878003e1a30f46fb, topology_type: Single, servers: [<ServerDescription ('{service_name}.mongo.cosmos.azure.com', 10255) server_type: Unknown, rtt: None, error=NetworkTimeout('{service_name}.mongo.cosmos.azure.com:10255: timed out')>]>"
}```

Solution

  • ServerSelectionTimeoutError

    The above error may occur because of using MongoClient without importing it from pymongo. Try with the below code, it imports MongoClient from pymongo.

    from pymongo import MongoClient
    
    username = "<user_name>"
    primary_key = "<primary_password>"
    service_name = "<service_name>"
    
    connection_string = (
        f"mongodb://{username}:{primary_key}@{service_name}.mongo.cosmos.azure.com:10255/"
        "?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@{service_name}@"
    )
    
    try:
        client = MongoClient(connection_string, serverSelectionTimeoutMS=60000)
    
        db_names = client.list_database_names()
        print("Connected successfully. Databases:")
        print(db_names)
    
    except Exception as e:
        print(f"Connection failed: {e}")
    

    Output:

    Connected successfully. Databases:
    ['newdb']