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

基于Beanie ODM、FastAPI与MongoDB优化JSON响应引用ID格式的问题

优化Beanie ODM中JSON响应的引用格式(高效处理批量数据)

直接通过自定义Beanie字段和Link子类,把序列化逻辑嵌入底层,避免手动遍历格式化的性能损耗,具体实现步骤如下:

1. 自定义带前缀的主键字段

针对自身_id的booking_xxx格式需求,继承PydanticObjectId实现带前缀的序列化:

from beanie import PydanticObjectId
from pydantic_core import core_schema

class PrefixedObjectId(PydanticObjectId):
    prefix: str
    
    @classmethod
    def __get_pydantic_core_schema__(cls, source_type, handler):
        base_schema = super().__get_pydantic_core_schema__(source_type, handler)
        return core_schema.no_info_wrap_validator_function(
            cls._serialize,
            base_schema,
            serialization=core_schema.plain_serializer_function_ser_schema(cls._serialize)
        )
    
    @classmethod
    def _serialize(cls, value: PydanticObjectId) -> str:
        return f"{cls.prefix}_{str(value)}"

# 针对Booking模型的专属ID类
class BookingId(PrefixedObjectId):
    prefix = "booking"

2. 自定义带集合前缀的Link字段

处理引用字段的account_xxx格式需求,继承Beanie的Link类重写序列化逻辑:

from beanie import Link
from pydantic import GetCoreSchemaHandler
from pydantic_core import core_schema

class PrefixedLink(Link):
    @classmethod
    def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        base_schema = super().__get_pydantic_core_schema__(source_type, handler)
        return core_schema.no_info_wrap_validator_function(
            cls._serialize_link,
            base_schema,
            serialization=core_schema.plain_serializer_function_ser_schema(cls._serialize_link)
        )
    
    @classmethod
    def _serialize_link(cls, value) -> str:
        # 直接从引用文档中取集合名和ID拼接
        return f"{value.__collection_name__}_{str(value.id)}"

3. 在Booking模型中应用自定义字段

把自定义字段替换原生字段,所有序列化逻辑自动生效:

from beanie import Document
from pydantic import Field
from models.account import Account  # 你的Account模型

class Booking(Document):
    id: BookingId = Field(default_factory=BookingId, alias="_id")
    account: PrefixedLink[Account]
    # 其他业务字段...
    
    class Settings:
        name = "bookings"

4. FastAPI中直接返回批量数据

现在查询批量数据时,不需要额外格式化,直接返回即可,性能和原生序列化一致:

from fastapi import FastAPI
from models.booking import Booking

app = FastAPI()

@app.get("/bookings")
async def get_all_bookings():
    # 直接返回10000条格式化后的结果
    return await Booking.find_all().to_list(10000)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:25:00