How do I retrieve records in MongoDB with PyMongo based on Flask URL variables?

Issue

Problem Statement

I am building an API that must retrieve documents from a mongodb database, and I need to define a route in the Flask app that allows me to use the Flask URL variable as a value in my mdb query.

I have tried the following:

@app.route("/infrastructure/<infrastructure_type>")
def get_infrastructure(infrastructure_type):
    infrastructure = db.infrastructure.find(jsonify(f'properties.type.primary: {infrastructure_type}'), projection = {"_id": False})
    return jsonify([resource for resource in infrastructure])

Expected results

I was expecting to be able to go to a route like http://127.0.0.1:5000/infrastructure/mine and see all of the documents whose primary type in the database is mine returned as JSON.

Actual results

I received a 500 Internal Server Error and the following error message:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/ben/Desktop/repos/rdcep/shotgun-api/app.py", line 23, in get_infrastructure
    infrastructure = db.infrastructure.find(jsonify(f'properties.type.primary: {infrastructure_type}'), projection = {"_id": False})
  File "/usr/local/lib/python3.9/site-packages/pymongo/collection.py", line 1523, in find
    return Cursor(self, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/pymongo/cursor.py", line 144, in __init__
    validate_is_mapping("filter", spec)
  File "/usr/local/lib/python3.9/site-packages/pymongo/common.py", line 494, in validate_is_mapping
    raise TypeError("%s must be an instance of dict, bson.son.SON, or "
TypeError: filter must be an instance of dict, bson.son.SON, or any other type that inherits from collections.Mapping

Example data from Mongo, showing the way the properties are nested

Example data from Mongo

Question

What do I need to do in order to get my query filter in a format that mongo will accept?

Solution

As mentioned by Alexandre Mahdhaoui in this answer, I needed to pass a dict as my filter argument, but for some reason my database required dot notation for access. This answer contains the complete solution:

@app.route("/infrastructure/<infrastructure_type>")
def get_infrastructure(infrastructure_type):
    infrastructure = db.infrastructure.find({'properties.type.primary': infrastructure_type}, projection = {"_id": False})
    return jsonify([resource for resource in infrastructure])

Answered By – bkleeman

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published