Mongoengine update_one+upsert vs. 弃用的 get_or_create

6 投票
1 回答
6197 浏览
提问于 2025-04-18 13:15

假设我有一组用 MongoEngine 定义的文档:

class Project(Document):
    name = StringField(required=True)
    client = StringField(required=True)
    code = StringField(required=True,unique=True)
    created = DateTimeField(required=True,default=datetime.datetime.now)

以前,我可以使用 get_or_create 方法来执行“插入或更新”的操作。比如说:

Project.objects().get_or_create(name="Test Project One",
                                client="Client One",
                                code="CL1-001")

这会把以下文档添加到集合中:

{
    "name": "Test Project One",
    "client": "Client One",
    "code": "CL1-001",
    "created": {
        "$date": "2014-07-14T14:00:38.024Z"
    }
}

现在这个方法 已经不推荐使用,推荐的替代方法是使用 update_one 并设置 upsert=True,像这样:

Project.objects(code="CL1-002").update_one(set__name="Test Project Two",
                                           set__client="Client One",
                                           upsert=True)

但这样做会导致添加到集合中的文档没有 created 字段:

{
    "client": "Client One",
    "code": "CL1-002",
    "name": "Test Project Two"
}

有没有办法在不出现竞争条件的情况下,用 MongoEngine 复制 get_or_create 的默认字段行为呢?

1 个回答

9

现在这个功能还没有自动支持,但是可以实现的——请提交一个请求,维护人员会进行审核。

与此同时,你可以使用 $setOnInsert 这个选项,它只会在插入数据时设置一个值,这样就能达到你需要的效果,比如:

Project.objects(code="CL1-002").update_one(set_on_insert__created=Project().created,
                                           set__name="Test Project Two",
                                           set__client="Client One",
                                           upsert=True)

撰写回答