概述

MongoDB 是一款开源的文档型NoSQL数据库。我们可以通过 updatereplacesave 等方法更新集合中的文档。要修改文档中的特定字段,需要使用 $set$inc 等操作符。

本文将深入探讨如何使用 updatereplace 查询修改文档的多个字段。我们先从MongoDB Shell查询入手,再对应实现Java代码。

使用Shell查询更新不同字段

首先创建测试数据库 baeldung 和集合 employee

use baeldung;
db.createCollection(employee);

插入测试数据:

db.employee.insertMany([
    {
        "employee_id": 794875,
        "employee_name": "David Smith",
        "job": "Sales Representative",
        "department_id": 2,
        "salary": 20000,
        "hire_date": NumberLong("1643969311817")
    },
    {
        "employee_id": 794876,
        "employee_name": "Joe Butler",
        "job": "Sales Manager",
        "department_id": 3,
        "salary": 30000,
        "hire_date": NumberLong("1645338658000")
    }
]);

更新单个文档的多个字段

使用 $set$inc 操作符组合更新:

  • $set:直接设置新值
  • $inc:对数值字段进行增量修改
db.employee.updateOne(
    {
        "employee_id": 794875,
        "employee_name": "David Smith"
    },
    {
        $set:{
            department_id:3,
            job:"Sales Manager"
        }
    }
);

混合使用操作符的示例:

db.employee.updateOne(
    {
        "employee_id": 794875
    },
    {
        $inc: {
            department_id: 1
        },
        $set: {
            job: "Sales Manager"
        }
    }
);

更新多个文档的多个字段

批量更新需要添加 multi: true 选项(或使用 updateMany):

db.employee.update(
    {
        "job": "Sales Representative"
    },
    {
        $inc: { 
            salary: 10000
        }, 
        $set: { 
            department_id: 5
        }
    },
    {
        multi: true 
    }
);

更简洁的 updateMany 写法:

db.employee.updateMany(
    {
        "job": "Sales Representative"
    },
    {
        $inc: {
            salary: 10000
        },
        $set: {
            department_id: 5
        }
    }
);

更新多个字段时的常见问题

踩坑警告:在单个查询中重复使用同一操作符时,MongoDB只会执行最后一次操作:

db.employee.updateMany(
    {
        "employee_id": 794875
    },
    {
        $set: {
            department_id: 3
        },
        $set: {
            job:"Sales Manager"
        }
    }
);

结果只有 job 字段被更新,department_id 保持不变。正确做法是将多个字段放在同一个操作符中。

使用Java驱动更新字段

先建立数据库连接:

MongoClient mongoClient = new MongoClient(new MongoClientURI("mongodb://localhost:27017"));
MongoDatabase database = mongoClient.getDatabase("baeldung");
MongoCollection<Document> collection = database.getCollection("employee");

使用DBObject

BasicDBObject 继承自 LinkedHashMap,采用键值对结构:

BasicDBObject searchQuery = new BasicDBObject("employee_id", 794875);
BasicDBObject updateFields = new BasicDBObject();
updateFields.append("department_id", 3);
updateFields.append("job", "Sales Manager");
BasicDBObject setQuery = new BasicDBObject();
setQuery.append("$set", updateFields);
UpdateResult updateResult = collection.updateMany(searchQuery, setQuery);

使用BSON文档

更现代的写法,利用 FiltersUpdates 工具类:

UpdateResult updateQueryResult = collection.updateMany(
    Filters.eq("employee_id", 794875),
    Updates.combine(
        Updates.set("department_id", 3),
        Updates.set("job", "Sales Manager")
    )
);

使用替换查询

简单粗暴的方案:直接用新文档替换旧文档:

db.employee.replaceOne(
    {
        "employee_id": 794875
    },
    {
        "employee_id": 794875,
        "employee_name": "David Smith",
        "job": "Sales Manager",
        "department_id": 3,
        "salary": 30000,
        "hire_date": NumberLong("1643969311817")
    }
);

注意:替换操作会完全覆盖文档,未指定的字段将被删除。

结论

本文系统介绍了MongoDB多字段更新的三种核心方案:

  1. 操作符更新:通过 $set/$inc 精准修改字段
  2. Java驱动实现:推荐使用BSON文档的链式调用
  3. 文档替换:适用于全量更新的场景

关键要点:

  • 避免在单个查询中重复使用同一操作符
  • 批量更新优先选择 updateMany
  • 部分更新用操作符,全量更新用替换

完整代码示例可在GitHub仓库获取。


原始标题:Update Multiple Fields in a MongoDB Document