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

如何在Python中以类属性形式访问字段构建MongoDB查询条件?

解决方案

方法一:利用attrs字段元数据自动生成类属性

通过attrs的field元数据标记字段路径,在类加载时自动生成对应的类级属性,返回MongoDB查询所需的字符串路径:

from attrs import define, field

@define(slots=True)
class User:
    @define()
    class UserDetails:
        status: UserStatus = field(default=UserStatus.ALIVE, metadata={"path": "status"})
        address: str = field(default=None, metadata={"path": "address"})

    user_id: CustomTypeId = field(default=None, metadata={"path": "user_id"})
    details: UserDetails = field(factory=UserDetails, metadata={"path": "details"})

    @classmethod
    def __init_subclass__(cls):
        # 处理当前类的字段映射
        for attr in cls.__attrs_attrs__:
            path = attr.metadata.get("path")
            if path:
                setattr(cls, attr.name, path)
        # 处理嵌套类的字段,拼接完整路径
        for nested_name, nested_cls in cls.__dict__.items():
            if hasattr(nested_cls, "__attrs_attrs__"):
                parent_path = getattr(cls, nested_name)
                for attr in nested_cls.__attrs_attrs__:
                    full_path = f"{parent_path}.{attr.metadata.get('path')}"
                    setattr(nested_cls, attr.name, full_path)

# 触发嵌套类属性初始化
User.__init_subclass__()

使用时直接通过类访问属性获取路径:

db[UserCollection].find({User.user_id: 'newid', User.details.status: 'ALIVE'})

方法二:自定义描述符实现类/实例双访问逻辑

实现一个描述符类,类级别访问返回查询路径,实例级别访问返回字段值:

from attrs import define, field

class MongoFieldDescriptor:
    def __init__(self, path, default=None):
        self.path = path
        self.default = default
        self.attr_name = path.split(".")[-1]

    def __get__(self, instance, owner):
        if instance is None:
            return self.path
        return instance.__dict__.get(self.attr_name, self.default)

@define(slots=True)
class User:
    @define()
    class UserDetails:
        status = MongoFieldDescriptor("details.status", UserStatus.ALIVE)
        address = MongoFieldDescriptor("details.address", None)

    user_id = MongoFieldDescriptor("user_id")
    details: UserDetails = field(factory=UserDetails)

这种方案更轻量,直接通过预定义路径实现需求,无需额外初始化逻辑。

常规替代方案

如果不想手动实现,可以直接使用基于attrs的成熟MongoDB ORM库,比如attrs-mongo或mongomantic,这些库已经封装了字段映射、查询构建、数据校验等功能,既能保证数据结构一致性,又能减少重复开发工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:35:56