MongoDB文档更新 #

一、更新概述 #

1.1 更新类型 #

MongoDB提供三种更新方式:

方法 说明
updateOne 更新单个文档
updateMany 更新多个文档
replaceOne 替换整个文档

1.2 更新操作符 #

javascript
// 更新操作符
{
    $set: { ... },      // 设置字段
    $unset: { ... },    // 删除字段
    $inc: { ... },      // 增加数值
    $push: { ... },     // 添加数组元素
    $pull: { ... }      // 删除数组元素
}

二、updateOne方法 #

2.1 基本更新 #

javascript
// 更新单个文档
db.users.updateOne(
    { name: "John" },           // 过滤条件
    { $set: { age: 26 } }       // 更新操作
)

// 输出
{
    "acknowledged": true,
    "matchedCount": 1,
    "modifiedCount": 1
}

2.2 更新多个字段 #

javascript
// 更新多个字段
db.users.updateOne(
    { name: "John" },
    {
        $set: {
            age: 26,
            email: "john.new@example.com",
            city: "Shanghai"
        }
    }
)

2.3 更新嵌套字段 #

javascript
// 更新嵌套字段
db.users.updateOne(
    { name: "John" },
    {
        $set: {
            "address.city": "Shanghai",
            "address.zipCode": "200000"
        }
    }
)

2.4 更新数组元素 #

javascript
// 更新数组元素(按索引)
db.users.updateOne(
    { name: "John" },
    { $set: { "hobbies.0": "reading" } }
)

// 更新数组元素(按条件)
db.users.updateOne(
    { name: "John", "scores.type": "math" },
    { $set: { "scores.$.value": 95 } }
)

2.5 更新选项 #

javascript
// 更新选项
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26 } },
    {
        upsert: true,           // 不存在则插入
        writeConcern: { w: "majority" }
    }
)

三、updateMany方法 #

3.1 批量更新 #

javascript
// 更新多个文档
db.users.updateMany(
    { status: "inactive" },     // 过滤条件
    { $set: { status: "active" } }  // 更新操作
)

// 输出
{
    "acknowledged": true,
    "matchedCount": 10,
    "modifiedCount": 10
}

3.2 条件更新 #

javascript
// 条件更新
db.users.updateMany(
    { age: { $lt: 18 } },
    { $set: { status: "minor" } }
)

// 复杂条件更新
db.orders.updateMany(
    {
        status: "pending",
        createdAt: { $lt: new Date("2024-01-01") }
    },
    { $set: { status: "expired" } }
)

3.3 数组更新 #

javascript
// 更新数组中的所有匹配元素
db.users.updateMany(
    { "scores.type": "math" },
    { $set: { "scores.$[].passed": true } }
)

// 使用$[]更新所有元素
db.users.updateMany(
    { name: "John" },
    { $inc: { "scores.$[]": 5 } }
)

四、replaceOne方法 #

4.1 替换文档 #

javascript
// 替换整个文档(保留_id)
db.users.replaceOne(
    { name: "John" },
    {
        name: "John Doe",
        email: "john.doe@example.com",
        age: 30,
        city: "Shanghai"
    }
)

// 输出
{
    "acknowledged": true,
    "matchedCount": 1,
    "modifiedCount": 1
}

4.2 替换与更新的区别 #

javascript
// updateOne:只更新指定字段
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26 } }
)
// 其他字段保持不变

// replaceOne:替换整个文档
db.users.replaceOne(
    { name: "John" },
    { name: "John", age: 26 }
)
// 其他字段被删除(除了_id)

五、更新操作符 #

5.1 字段操作符 #

$set - 设置字段值

javascript
// 设置字段
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26, city: "Shanghai" } }
)

// 设置嵌套字段
db.users.updateOne(
    { name: "John" },
    { $set: { "address.city": "Shanghai" } }
)

$unset - 删除字段

javascript
// 删除字段
db.users.updateOne(
    { name: "John" },
    { $unset: { middleName: "" } }
)

// 删除嵌套字段
db.users.updateOne(
    { name: "John" },
    { $unset: { "address.zipCode": "" } }
)

$inc - 增加数值

javascript
// 增加数值
db.users.updateOne(
    { name: "John" },
    { $inc: { age: 1 } }
)

// 减少数值
db.users.updateOne(
    { name: "John" },
    { $inc: { balance: -100 } }
)

// 增加多个字段
db.users.updateOne(
    { name: "John" },
    { $inc: { age: 1, score: 10 } }
)

$mul - 乘法

javascript
// 乘法运算
db.products.updateOne(
    { name: "Product A" },
    { $mul: { price: 1.1 } }  // 价格增加10%
)

$rename - 重命名字段

javascript
// 重命名字段
db.users.updateOne(
    { name: "John" },
    { $rename: { "oldName": "newName" } }
)

$setOnInsert - 插入时设置

javascript
// 仅在插入时设置字段
db.users.updateOne(
    { name: "John" },
    {
        $set: { age: 26 },
        $setOnInsert: { createdAt: new Date() }
    },
    { upsert: true }
)

$currentDate - 设置当前日期

javascript
// 设置当前日期
db.users.updateOne(
    { name: "John" },
    { $currentDate: { updatedAt: true } }
)

// 设置时间戳
db.users.updateOne(
    { name: "John" },
    { $currentDate: { lastModified: { $type: "timestamp" } } }
)

$min - 最小值

javascript
// 如果新值小于当前值则更新
db.products.updateOne(
    { name: "Product A" },
    { $min: { price: 50 } }
)

$max - 最大值

javascript
// 如果新值大于当前值则更新
db.products.updateOne(
    { name: "Product A" },
    { $max: { price: 100 } }
)

5.2 数组操作符 #

$push - 添加元素

javascript
// 添加单个元素
db.users.updateOne(
    { name: "John" },
    { $push: { hobbies: "reading" } }
)

// 添加多个元素
db.users.updateOne(
    { name: "John" },
    { $push: { hobbies: { $each: ["reading", "swimming"] } } }
)

// 添加并排序
db.users.updateOne(
    { name: "John" },
    {
        $push: {
            scores: {
                $each: [85, 90, 78],
                $sort: -1,
                $slice: 10  // 只保留前10个
            }
        }
    }
)

// 添加到指定位置
db.users.updateOne(
    { name: "John" },
    {
        $push: {
            scores: {
                $each: [95],
                $position: 0  // 插入到开头
            }
        }
    }
)

$pull - 删除元素

javascript
// 删除匹配元素
db.users.updateOne(
    { name: "John" },
    { $pull: { hobbies: "reading" } }
)

// 删除多个元素
db.users.updateOne(
    { name: "John" },
    { $pull: { scores: { $lt: 60 } } }  // 删除小于60的分数
)

// 删除嵌套数组元素
db.users.updateOne(
    { name: "John" },
    { $pull: { "comments": { userId: 123 } } }
)

$pullAll - 删除多个值

javascript
// 删除多个指定值
db.users.updateOne(
    { name: "John" },
    { $pullAll: { hobbies: ["reading", "swimming"] } }
)

$pop - 删除首尾元素

javascript
// 删除最后一个元素
db.users.updateOne(
    { name: "John" },
    { $pop: { hobbies: 1 } }
)

// 删除第一个元素
db.users.updateOne(
    { name: "John" },
    { $pop: { hobbies: -1 } }
)

$addToSet - 添加唯一元素

javascript
// 添加唯一元素(已存在则不添加)
db.users.updateOne(
    { name: "John" },
    { $addToSet: { hobbies: "reading" } }
)

// 添加多个唯一元素
db.users.updateOne(
    { name: "John" },
    { $addToSet: { hobbies: { $each: ["reading", "swimming"] } } }
)

$each - 批量操作

javascript
// 与$push配合使用
db.users.updateOne(
    { name: "John" },
    { $push: { scores: { $each: [85, 90, 78] } } }
)

// 与$addToSet配合使用
db.users.updateOne(
    { name: "John" },
    { $addToSet: { tags: { $each: ["tag1", "tag2"] } } }
)

$sort - 数组排序

javascript
// 数组排序
db.users.updateOne(
    { name: "John" },
    {
        $push: {
            scores: {
                $each: [],
                $sort: -1
            }
        }
    }
)

$slice - 限制数组长度

javascript
// 限制数组长度
db.users.updateOne(
    { name: "John" },
    {
        $push: {
            logs: {
                $each: ["log1", "log2"],
                $slice: -10  // 只保留最后10个
            }
        }
    }
)

$position - 指定位置插入

javascript
// 在指定位置插入
db.users.updateOne(
    { name: "John" },
    {
        $push: {
            scores: {
                $each: [95],
                $position: 0
            }
        }
    }
)

5.3 位操作符 #

$bit - 位运算

javascript
// 位与运算
db.users.updateOne(
    { name: "John" },
    { $bit: { flags: { and: 5 } } }
)

// 位或运算
db.users.updateOne(
    { name: "John" },
    { $bit: { flags: { or: 1 } } }
)

// 位异或运算
db.users.updateOne(
    { name: "John" },
    { $bit: { flags: { xor: 3 } } }
)

六、upsert操作 #

6.1 基本upsert #

javascript
// upsert:不存在则插入
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26 } },
    { upsert: true }
)

// 输出
{
    "acknowledged": true,
    "matchedCount": 0,
    "modifiedCount": 0,
    "upsertedId": ObjectId("...")
}

6.2 条件upsert #

javascript
// 条件upsert
db.users.updateOne(
    { email: "john@example.com" },
    {
        $set: { name: "John", age: 26 },
        $setOnInsert: { createdAt: new Date() }
    },
    { upsert: true }
)

6.3 批量upsert #

javascript
// 批量upsert
db.users.bulkWrite([
    {
        updateOne: {
            filter: { name: "John" },
            update: { $set: { age: 26 } },
            upsert: true
        }
    },
    {
        updateOne: {
            filter: { name: "Jane" },
            update: { $set: { age: 28 } },
            upsert: true
        }
    }
])

七、findAndModify #

7.1 findOneAndUpdate #

javascript
// 查找并更新
db.users.findOneAndUpdate(
    { name: "John" },
    { $set: { age: 26 } },
    {
        returnNewDocument: true,  // 返回更新后的文档
        sort: { age: -1 },
        upsert: true
    }
)

7.2 findOneAndReplace #

javascript
// 查找并替换
db.users.findOneAndReplace(
    { name: "John" },
    { name: "John Doe", age: 30 },
    { returnNewDocument: true }
)

八、更新性能 #

8.1 更新优化 #

javascript
// 使用索引加速更新
db.users.createIndex({ name: 1 })
db.users.updateOne({ name: "John" }, { $set: { age: 26 } })

// 批量更新
db.users.updateMany({ status: "inactive" }, { $set: { status: "active" } })

8.2 更新选项 #

javascript
// 更新选项
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26 } },
    {
        writeConcern: { w: "majority", j: true },
        bypassDocumentValidation: false
    }
)

九、最佳实践 #

9.1 使用合适的操作符 #

javascript
// 推荐:使用$set只更新需要的字段
db.users.updateOne(
    { name: "John" },
    { $set: { age: 26 } }
)

// 不推荐:使用replaceOne替换整个文档
db.users.replaceOne(
    { name: "John" },
    { name: "John", age: 26 }
)

9.2 使用upsert #

javascript
// 推荐:使用upsert避免重复检查
db.users.updateOne(
    { email: "john@example.com" },
    { $set: { name: "John", age: 26 } },
    { upsert: true }
)

// 不推荐:先查询再插入
const user = db.users.findOne({ email: "john@example.com" })
if (user) {
    db.users.updateOne({ email: "john@example.com" }, { $set: { age: 26 } })
} else {
    db.users.insertOne({ email: "john@example.com", name: "John", age: 26 })
}

9.3 批量更新 #

javascript
// 推荐:使用updateMany
db.users.updateMany({ status: "inactive" }, { $set: { status: "active" } })

// 不推荐:循环更新
db.users.find({ status: "inactive" }).forEach(user => {
    db.users.updateOne({ _id: user._id }, { $set: { status: "active" } })
})

十、总结 #

更新操作速查表:

方法 说明 示例
updateOne 更新单个文档 db.coll.updateOne({…}, {…})
updateMany 更新多个文档 db.coll.updateMany({…}, {…})
replaceOne 替换文档 db.coll.replaceOne({…}, {…})

常用操作符:

操作符 说明
$set 设置字段值
$unset 删除字段
$inc 增加数值
$push 添加数组元素
$pull 删除数组元素
$addToSet 添加唯一元素

下一步,让我们学习文档删除!

最后更新:2026-03-27