与 MongoDB 结合使用时,Dataclass 中的 '_id' 应该如何处理?

How should I deal with '_id' in Dataclass when used in combination with MongoDB?

我有一个 MongoDB 并且想将每个文档存储为 python 数据 class 的一个实例。我对“_id”有疑问。当我创建本地实例时,我不想分配“_id”。但是,在检索文档时,实例应包含“_id”。

我的方法是将“_id”设置为 None。当我将实例插入数据库时​​,这不起作用。值 None 作为“_id”传递。

有没有一种方法可以使用数据class 创建一个模型,这样我就可以将本地数据和检索到的数据存储为相同 class 的实例?

from dataclasses import dataclass 
from typing import List

from bson import ObjectId

@dataclass
class Article:
    name: str
    quantity: int
    _id: ObjectId = None
    description: str = ""

插入本地实例

import dataclasses
from pymongo import MongoClient

article = Article(name="pen", description="A writing device", quantity=100)

self.client = MongoClient()
self.db = self.client.warehouse
self.collection = self.db["articles"]
res = self.collection.insert_one(dataclasses.asdict(article)) # <-- Should not contain "_id"

检索文档

res = self.collection.find_one("_id": ObjectID())
article = Article(**res) # <-- Article should contain id
from dataclasses import dataclass, asdict
from typing import Optional


@dataclass
class Article:
    name: str
    quantity: int
    id: Optional[int] = None
    description: str = ''

    def to_short_dict(self):
        result = asdict(self)
        result.pop('id')
        return result


# not contain "id"
input_data = {
    'name': 'pen', 'quantity': 100, 'description': 'A writing device',
}
article = Article(**input_data)
assert article.to_short_dict() == input_data

# contain "id"
input_data = {
    'id': 1,
    'name': 'pen', 'quantity': 100, 'description': 'A writing device',
}
article = Article(**input_data)
assert asdict(article) == input_data

我试图想出一个更通用的解决方案:

我创建了一个接口 MongoDataclass,我的所有模型都继承自该接口。该接口包含一个方法,该方法 returns 所有值不是 None 的键值对作为字典。

我认为这是有道理的,因为 MongoDB 是无模式的,我不想在我的文档中存储任何 None 值。这也解决了“_id”的问题。

import abc
from dataclasses import dataclass

@dataclass
class MongoDataclass(abc.ABC):

    def as_json_wo_none(self):
        return {key: value for key, value in dataclasses.asdict(self).items() if value is not None}