AWS DocumentDB 语法不同于 MongoDB for UpdateMany

问题描述

从 mongo > documentDB 迁移后,我尝试使用 substr 执行更新,但是我收到一个奇怪的错误

以下使用 pymongo 在 Mongo 4.0 上工作:

    await db[cls.colname].update_many(
        {'$or': [{'preview_title': {'$exists': False}},{'preview_title': None}]},[{'$set': {'preview_title': {'$substr': ['$title',70]}}}],)

等效的 mongo shell 命令也有效:

db.getCollection('pages').updateMany({'$or': [{'preview_title': {'$exists': false}},{'preview_title': null}]},[{'$set': {'preview_title': {'$substrBytes': ['$title',70]}}}])

但是,在切换到 AWS DocumentDB 后,它不接受作为数组的更新,否则会返回此错误:“MongoError: Wrong type for parameter u” image

如果我将命令更改为以下内容,它将起作用(基本上只需从更新部分中删除方括号):

db.getCollection('pages').updateMany({'$or': [{'preview_title': {'$exists': false}},{'$set': {'preview_title': {'$substr': ['$title',70]}}})

这很好,但是,等效的 pymongo 调用似乎不起作用:

await db[cls.colname].update_many(
            {'$or': [{'preview_title': {'$exists': False}},70]}}},)

它返回以下错误: pymongo.errors.WriteError:文档不能有 $ 前缀字段名称:$substr

解决方法

在更新时传递数组称为“使用聚合管道更新”。 DocumentDB 显然没有实现这一点(在许多其他 MongoDB 功能中)。

当您从更新中删除数组时,您将从使用 https://docs.mongodb.com/manual/reference/operator/aggregation/set/ 更改为使用 https://docs.mongodb.com/manual/reference/operator/update/set/。你会注意到更新 $set 不接受像聚合 $set 这样的表达式。因此,您使用 $set 的 shell 更新将一个(嵌套的)文档 {'$substr': ['$title',70]} 写入 preview 字段。通常以美元开头的键是不可查询的,因为 MongoDB 运算符使用美元前缀,因此将这样的文档写入字段是一个坏主意。 Pymongo 会告诉您这一点并拒绝该操作。 shell 允许这样做,因为它也被 MongoDB 服务器工程师内部用于测试,因此它允许完成各种奇怪/不寻常的事情。