Why is find_one() timing out when find() works just fine using MongoDB?

Question:

The code below connects to MongoDB, then attempts to find the specified record, which exists. The collections are very small.

client = pymongo.MongoClient("PRIVATE_MONGO_ACCESS_HERE?retryWrites=true&w=majority")
db = client.my_db
score_holder = db['app_data'].find_one({'score_holder': True})

Result: pymongo.errors.ServerSelectionTimeoutError

I’m pretty sure the above code was working fine a couple weeks ago – no code has changed since and I don’t recall upgrading anything. I don’t see anything on MongoDB about changes to this, nor anybody else having this issue.

I can replace the last line with this:

score_holder = db['app_data'].find({'score_holder': True})

And I get a result: <pymongo.cursor.Cursor object>

This means we can be sure I am connecting to the database, I have the ability to retrieve records, and this particular record does exist.

I’ve also tried to just find with no arguments because why not:

score_holder = db['app_data'].find_one()

Result: pymongo.errors.ServerSelectionTimeoutError

Why would I time out with one method and not another?

Asked By: hexmerald

||

Answers:

This means we can be sure I am connecting to the database

I suspect that this claim is incorrect which is resulting the conclusion about the overall problem similarly being incorrect.

What I believe is happening here is that the find_one() call is executing immediately but the find() is not. A (PyMongo) cursor object has been returned by the call to find() but the code itself hasn’t actually communicated with the database yet. Try reading from the cursor and see what happens, see this demonstration below where no database is running at the provided address:

>>> client = pymongo.MongoClient('172.17.0.2')
>>> db = client.test
>>> score_holder = db['foo'].find()
>>> print(score_holder)
<pymongo.cursor.Cursor object at 0x7fb7b876d220>
>>> for doc in score_holder:
...     print(doc)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/cursor.py", line 1248, in next
    if len(self.__data) or self._refresh():
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/cursor.py", line 1139, in _refresh
    self.__session = self.__collection.database.client._ensure_session()
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/mongo_client.py", line 1712, in _ensure_session
    return self.__start_session(True, causal_consistency=False)
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/mongo_client.py", line 1657, in __start_session
    self._topology._check_implicit_session_support()
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/topology.py", line 538, in _check_implicit_session_support
    self._check_session_support()
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/topology.py", line 554, in _check_session_support
    self._select_servers_loop(
  File "/home/charris/.local/lib/python3.8/site-packages/pymongo/topology.py", line 238, in _select_servers_loop
    raise ServerSelectionTimeoutError(
pymongo.errors.ServerSelectionTimeoutError: 172.17.0.2:27017: [Errno 113] No route to host, Timeout: 30s, Topology Description: <TopologyDescription id: 6363dddd5a1caf7896d4cc13, topology_type: Unknown, servers: [<ServerDescription ('172.17.0.2', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('172.17.0.2:27017: [Errno 113] No route to host')>]>
>>>

The answer to your current question is that both find_one() and find() timeout when they are executed. Therefore you should go back and review connectivity altogether between the client where this code is running and the database itself.

Answered By: user20042973