You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python+FastAPI中MongoDB日期范围过滤无结果问题排查

问题根源与解决方案

核心问题是D/M/Y格式的字符串无法正确按日期逻辑比较——MongoDB对字符串的比较是按字符顺序逐位判断的,而非实际日期的先后关系,这直接导致你的查询条件逻辑失效。

举个例子:集合中start_date为"15/03/2024",你传入的结束日期转成D/M/Y是"01/04/2024",字符串比较时"15/03/2024"会被判定为大于"01/04/2024"(因为第一个字符1比0大),但实际日期3月15日早于4月1日,这就导致符合条件的文档被错误过滤。

解决方法

方法1:查询时转换日期类型(无需修改现有数据)

使用MongoDB的$dateFromString操作符,将集合中的字符串日期转换为Date类型后再做比较,确保逻辑正确。示例代码如下:

from datetime import datetime
from fastapi import FastAPI, Query
import motor.motor_asyncio

app = FastAPI()
client = motor.motor_asyncio.AsyncIOMotorClient("mongodb://localhost:27017")
db = client.your_database_name

@app.get("/filter-items")
async def filter_items(start: str = Query(...), end: str = Query(...)):
    # 转换传入的Y-M-D日期为datetime对象
    input_start = datetime.strptime(start, "%Y-%m-%d")
    input_end = datetime.strptime(end, "%Y-%m-%d")
    
    # 构建带日期转换的查询条件
    query = {
        "$expr": {
            "$and": [
                {"$lte": [
                    {"$dateFromString": {"dateString": "$start_date", "format": "%d/%m/%Y"}},
                    input_end
                ]},
                {"$gte": [
                    {"$dateFromString": {"dateString": "$final_date", "format": "%d/%m/%Y"}},
                    input_start
                ]}
            ]
        }
    }
    
    # 执行异步查询
    cursor = db.your_collection.find(query)
    results = await cursor.to_list(length=None)
    return results

方法2:批量更新数据为Date类型(推荐长期方案)

如果数据量不大,建议直接将集合中的start_date和final_date字段从字符串改为Date类型,这样后续查询无需每次转换,性能更优。批量更新脚本示例:

async def batch_update_dates():
    cursor = db.your_collection.find({"start_date": {"$type": "string"}})
    async for doc in cursor:
        # 转换字符串日期为datetime对象
        start_date = datetime.strptime(doc["start_date"], "%d/%m/%Y")
        final_date = datetime.strptime(doc["final_date"], "%d/%m/%Y")
        
        # 更新文档字段类型
        await db.your_collection.update_one(
            {"_id": doc["_id"]},
            {"$set": {"start_date": start_date, "final_date": final_date}}
        )

后续查询时,直接用datetime对象比较即可,无需额外转换:

query = {
    "start_date": {"$lte": input_end},
    "final_date": {"$gte": input_start}
}

内容的提问来源于stack exchange,提问作者Diego L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 06:10:26