FastAPI对接MongoDB按时间范围查询触发InvalidId错误如何解决
问题定位与修复方案
问题原因定位
- 路由参数匹配错误:你采用的
/{date_from}_{date_to}路径写法,FastAPI无法自动以下划线为分隔符拆分两个日期参数,会把整个2021-01-01_2021-12-31识别为单个date_from参数的值,同时date_to参数缺失。如果接口同路径下存在/{request_id}这类默认匹配ObjectId的路由,就会触发该路由的参数解析逻辑,将整个日期字符串尝试转为ObjectId,抛出你遇到的bson.errors.InvalidId报错。 - 参数未声明类型:你没有给路由参数标注
date类型,FastAPI无法自动将传入的日期字符串转为Python的date类型,后续和MongoDB中存储的日期类型字段比对会出现类型不匹配问题。 - MongoDB查询逻辑错误:
range()函数仅支持数字范围迭代,不能接收MongoDB的find游标作为参数,且时间范围查询需要使用MongoDB的查询运算符$gte(大于等于)和$lte(小于等于),不能分开两次调用find。
具体修复步骤
1. 路由(Route.py)修改
将路径参数改为斜杠分隔,同时明确标注参数类型,避免参数匹配错误:
from datetime import date from fastapi import Path @router.get("/{date_from}/{date_to}") async def get_request_year( date_from: date = Path(..., description="开始日期,格式为YYYY-MM-DD"), date_to: date = Path(..., description="结束日期,格式为YYYY-MM-DD") ): request = await retrive_year_requests(date_from, date_to) if request: return request return ErrorRequestModel("An error occurred.", 404, "request doesn't exist.")
修改后访问路径变为http://localhost:8000/request/2021-01-01/2021-12-31。
2. 数据库查询(database.py)修改
修正MongoDB的时间范围查询逻辑:
async def retrive_year_requests(date_from: date, date_to: date): requests = [] # 单条查询命中时间区间内的所有数据 query = {"dates": {"$gte": date_from, "$lte": date_to}} async for request in request_collection.find(query): requests.append(request_helper(request)) return requests
3. 可选:避免同路径路由冲突
如果你的路由文件中还有@router.get("/{request_id}")这类接收单个参数的路由,建议给参数加正则限制,确保只匹配ObjectId格式的参数:
from fastapi import Path @router.get("/{request_id}") async def get_single_request( request_id: str = Path(..., regex=r"^[0-9a-fA-F]{24}$") ): # 单条数据查询逻辑
内容的提问来源于stack exchange,提问作者Artur_marc
相关产品推荐
相关产品推荐

