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

FastAPI构建按日期查询MongoDB股票预测接口遇422错误求助

问题原因及解决方案

核心问题分析

  1. 422错误根源:接口路径参数声明为datetime.datetime,但传入的是YYYY-MM-DD格式的纯日期字符串,FastAPI无法将其自动解析为带时间的datetime对象,导致参数验证失败。
  2. MongoDB查询不匹配:数据库中存储的日期是带UTC时区的完整datetime(如2023-05-19T00:00:00.000+00:00),直接用datetime.date对象查询会匹配不到数据。
  3. 模型字段不匹配:声明的Predictions模型包含多余的symbol字段,与数据库实际的id_、date、predicted三个字段结构不符,会导致数据解析错误。

修正步骤及代码

1. 调整路径参数类型

将接口参数从datetime.datetime改为datetime.date,FastAPI会自动处理YYYY-MM-DD格式的输入。

2. 构造正确的MongoDB日期查询条件

由于数据库存储的是带时间的UTC日期,需要查询指定日期当天00:00到次日00:00的所有文档,确保匹配该日期的所有预测数据。

3. 修正数据模型字段

移除多余的symbol字段,确保模型与数据库文档结构一致;这里默认数据库使用MongoDB原生的_id作为ID字段,若实际是自定义id_,可对应修改模型字段别名。

修正后的完整代码

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from bson import ObjectId
from typing import List
import motor.motor_asyncio
import datetime
from datetime import timezone

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

class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid objectid")
        return ObjectId(v)

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")

# 修正模型,匹配数据库实际字段
class Predictions(BaseModel):
    id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
    date: datetime.datetime = Field(...)  # 对应数据库的带时区datetime字段
    predicted: float = Field(...)

    class Config:
        allow_population_by_field_name = True
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        schema_extra = {
            "example": {
                "date": "2023-04-28T00:00:00.000+00:00",
                "predicted": 0.0758,
            }
        }

@app.get(
    "/{date}", 
    response_description="获取指定日期的股票预测数据", 
    response_model=List[Predictions]
)
async def list_predictions_by_date(date: datetime.date):
    # 构造UTC时间范围:当天00:00到次日00:00
    start_date = datetime.datetime(date.year, date.month, date.day, tzinfo=timezone.utc)
    end_date = start_date + datetime.timedelta(days=1)
    
    # 查询该时间范围内的所有文档
    predictions = await db["predictions_live_API"].find({
        "date": {
            "$gte": start_date,
            "$lt": end_date
        }
    }).to_list(1000)
    
    if not predictions:
        raise HTTPException(status_code=404, detail=f"未找到日期{date}的预测数据")
    
    return predictions

额外说明

  • 如果数据库中实际的ID字段是自定义的id_而非MongoDB默认的_id,只需将模型中的id字段改为id: str = Field(..., alias="id_")(根据id_的实际类型调整)。
  • 测试接口时,直接传入YYYY-MM-DD格式的日期即可,比如访问http://localhost:8000/2023-05-19。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:58:16