HOWTO · MongoDB

使用 Java 批量更新 MongoDB 中的文档

本教程演示了如何使用 Java 对 MongoDB 中的文档进行批量更新。

本教程是关于使用 Java 驱动程序在 MongoDB 中执行文档的批量更新。我们还将学习如何通过添加新字段、更改现有字段或数组的值或删除文档来进行更新。

先决条件

对于本教程,我们将使用你必须遵循的以下工具。

  1. Java(我们使用的是 Java 18.0.1.1)
  2. MongoDB 服务器(我们使用的是 MongoDB 5.0.8)
  3. 代码编辑器或任何 Java IDE(我们使用的是 Apache NetBeans IDE 13)
  4. 使用 Maven 或 Gradle 的 Mongo Java Driver Dependencies; 我们在 Maven 中使用它

使用 Java 批量更新 MongoDB 中的文档

当我们需要更新数据库中的多个文档时,批量更新很有用。现在,问题是,我们要如何更新文档?

我们是否想通过添加新字段、更新现有字段或数组的值或删除文档来进行更新?要了解所有这些场景,让我们创建一个集合并插入两个文档。

创建集合:

db.createCollection('supervisor');

插入第一个文档:

db.supervisor.insertOne(
    {
          "firstname": "Mehvish",
          "lastname": "Ashiq",
          "gender": "Female",
          "contact" : {
              "email":"mehvishofficial@gmail.com",
              "phone" : [
                  {
                      "type" : "official",
                      "number" : "123456789"
                  },
                  {
                       "type" : "personal",
                       "number" : "124578369"
                  },
               ]
          },
          "entries" : [
              { "_id" : 1, "itemsperday" : [ 1,3,4,5,6,7 ] },
              { "_id" : 2, "itemperday" : [ 2,3,4,5,2,7 ] },
              { "_id" : 3, "itemperday" : [ 5,0,0,4,0,1 ] }
           ]
    }
);

插入第二个文件:

db.supervisor.insertOne(
    {
          "firstname": "Tahir",
          "lastname": "Raza",
          "gender": "Male",
          "contact" : {
              "email":"tahirraza@gmail.com",
              "phone" : [
                  {
                      "type" : "official",
                      "number" : "123478789"
                  },
                  {
                       "type" : "personal",
                       "number" : "122378369"
                  },
               ]
          },
          "entries" : [
              { "_id" : 1, "itemsperday" : [ 4,5,6,7,4,6 ] },
              { "_id" : 2, "itemperday" : [ 2,3,2,7,5,2 ] },
              { "_id" : 3, "itemperday" : [ 5,0,0,1,0,0 ] }
           ]
    }
);

填充集合后,你可以使用 db.supervisor.find().pretty(); 查看插入的文档。我们将从简单的解决方案开始,然后转向一些棘手但有趣的解决方案。

使用 updateMany() 通过向现有文档添加新字段来执行批量更新

示例代码:

// write your package where you want to save your source file
package com.voidtesting.javamongobulkupdateexample;

// import necessary libraries
import com.mongodb.BasicDBObject;
import com.mongodb.MongoException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

// Example_1
public class Example_1 {
  // main method
  public static void main(String[] args) {
    // Replace the connection string with your own connection string
    var uri = "mongodb://localhost:27017";

    // try block
    try (MongoClient mongoClient = MongoClients.create(uri)) {
      // print message if connection is successfully established
      System.out.println("Connected successfully to server.");

      // get the specified database from the MongoDB server
      MongoDatabase database = mongoClient.getDatabase("bulkUpdate");

      // get the specified collection from the selected database
      MongoCollection<Document> collection = database.getCollection("supervisor");

      // update documents by adding a new field and its value
      collection.updateMany(
          new BasicDBObject(), new BasicDBObject("$set", new BasicDBObject("status", "Good")));

      // print a new line
      System.out.println();

      // iterate over all documents of the selected collection
      // to print in Java IDE
      collection.find().forEach(doc -> {
        System.out.println(doc.toBsonDocument());
        System.out.println();
      }); // end forEach

    } // end try block

    // print error if unable to execute a command
    catch (MongoException error) {
      System.err.println("An error occurred while running a command: " + error);
    } // end catch block

  } // end main method
} // end Example_1

输出:

{
    "_id": {"$oid": "62a866e592fd89ad9c4932ed"},
    "firstname": "Mehvish",
    "lastname": "Ashiq",
    "gender": "Female",
    "contact": {
        "email": "mehvishofficial@gmail.com",
        "phone": [
            { "type": "official", "number": "123456789"},
            {"type": "personal", "number": "124578369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [1.0, 3.0, 4.0, 5.0, 6.0, 7.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 4.0, 5.0, 2.0, 7.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 4.0, 0.0, 1.0]}
     ],
     "status": "Good"
}

{
    "_id": {"$oid": "62a8670192fd89ad9c4932ee"},
    "firstname": "Tahir",
    "lastname": "Raza",
    "gender": "Male",
    "contact": {
        "email": "tahirraza@gmail.com",
        "phone": [
            {"type": "official", "number": "123478789"},
            {"type": "personal", "number": "122378369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [4.0, 5.0, 6.0, 7.0, 4.0, 6.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 2.0, 7.0, 5.0, 2.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 1.0, 0.0, 0.0]}
     ],
     "status": "Good"
}

我们已经为你格式化了输出(如上所示),但你将在 IDE 上每行看到一个文档。我们也可以使用 db.supervisor.find().pretty(); 在 mongo shell 上查看更新的文档。

对于此示例代码,我们使用 mongo 集合对象的 updateMany() 方法,该方法接受 filter 查询和 update 语句来更新匹配的文档。在这里,我们不是过滤文档,而是向所有现有文档添加一个名为 status 的新字段(参见上面给出的输出)。

使用 updateMany() 对匹配过滤器的多个文档中的现有字段执行批量更新

示例代码:

// write your package where you want to save your source file
package com.voidtesting.javamongobulkupdateexample;

// import necessary libraries
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Updates.combine;
import static com.mongodb.client.model.Updates.set;

import com.mongodb.MongoException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

// Example_2
public class Example_2 {
  // main method
  public static void main(String[] args) {
    // Replace the connection string with your own connection string
    var uri = "mongodb://localhost:27017";

    // try block
    try (MongoClient mongoClient = MongoClients.create(uri)) {
      // print message if connection is successfully established
      System.out.println("Connected successfully to server.");

      // get the specified database from the MongoDB server
      MongoDatabase database = mongoClient.getDatabase("bulkUpdate");

      // get the specified collection from the selected database
      MongoCollection<Document> collection = database.getCollection("supervisor");

      // update the filtered documents by updating the existing field
      collection.updateMany(eq("gender", "Female"), combine(set("gender", "F")));
      collection.updateMany(eq("gender", "Male"), combine(set("gender", "M")));

      System.out.println();
      // iterate over all documents of the selected collection
      // to print in Java IDE
      collection.find().forEach(doc -> {
        System.out.println(doc.toBsonDocument());
        System.out.println();
      }); // end forEach

    } // end try block

    // print error if unable to execute a command
    catch (MongoException error) {
      System.err.println("An error occurred while running a command: " + error);
    } // end catch block

  } // end main method
} // end Example_2

输出:

{
    "_id": {"$oid": "62a866e592fd89ad9c4932ed"},
    "firstname": "Mehvish",
    "lastname": "Ashiq",
    "gender": "F",
    "contact": {
        "email": "mehvishofficial@gmail.com",
        "phone": [
            { "type": "official", "number": "123456789"},
            {"type": "personal", "number": "124578369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [1.0, 3.0, 4.0, 5.0, 6.0, 7.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 4.0, 5.0, 2.0, 7.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 4.0, 0.0, 1.0]}
     ],
     "status": "Good"
}

{
    "_id": {"$oid": "62a8670192fd89ad9c4932ee"},
    "firstname": "Tahir",
    "lastname": "Raza",
    "gender": "M",
    "contact": {
        "email": "tahirraza@gmail.com",
        "phone": [
            {"type": "official", "number": "123478789"},
            {"type": "personal", "number": "122378369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [4.0, 5.0, 6.0, 7.0, 4.0, 6.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 2.0, 7.0, 5.0, 2.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 1.0, 0.0, 0.0]}
     ],
     "status": "Good"
}

此代码示例与上一个示例类似,但我们正在更新与过滤器匹配的所有文档中特定字段的值。

我们使用 updateMany()gender 等于 Femalegender 等于 Male 的所有文档执行批量更新。我们将 "gender": "Female""gender": "Male" 分别更改为 "gender":"F""gender":"M"

到目前为止,我们已经了解了如何使用 updateMany() 方法添加新字段或更新第一级现有字段的值。接下来,我们将学习使用 updateMany() 对满足过滤器查询的嵌入式文档进行批量更新。

使用 updateMany() 对匹配过滤器的嵌入文档执行批量更新

示例代码:

// write your package where you want to save your source file
package com.voidtesting.javamongobulkupdateexample;

// import necessary libraries
import com.mongodb.MongoException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import org.bson.Document;
import org.bson.conversions.Bson;

// Example_3
public class Example_3 {
  // main method
  public static void main(String[] args) {
    // Replace the connection string with your own connection string
    var uri = "mongodb://localhost:27017";

    // try block
    try (MongoClient mongoClient = MongoClients.create(uri)) {
      // print message if connection is successfully established
      System.out.println("Connected successfully to server.");

      // get the specified database from the MongoDB server
      MongoDatabase database = mongoClient.getDatabase("bulkUpdate");

      // get the specified collection from the selected database
      MongoCollection<Document> collection = database.getCollection("supervisor");
      // filter
      Bson where = new Document().append("contact.phone.type", "official");
      // update
      Bson update = new Document().append("contact.phone.$.type", "assistant");
      // set
      Bson set = new Document().append("$set", update);

      // update collection
      collection.updateMany(where, set, new UpdateOptions());

      // iterate over all documents of the selected collection
      // to print in Java IDE
      collection.find().forEach(doc -> {
        System.out.println(doc.toBsonDocument());
        System.out.println();
      }); // end forEach

    } // end try block

    // print error if unable to execute a command
    catch (MongoException error) {
      System.err.println("An error occurred while running a command: " + error);
    } // end catch block

  } // end main method
} // end Example_3

输出:

{
    "_id": {"$oid": "62a866e592fd89ad9c4932ed"},
    "firstname": "Mehvish",
    "lastname": "Ashiq",
    "gender": "F",
    "contact": {
        "email": "mehvishofficial@gmail.com",
        "phone": [
            { "type": "assistant", "number": "123456789"},
            {"type": "personal", "number": "124578369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [1.0, 3.0, 4.0, 5.0, 6.0, 7.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 4.0, 5.0, 2.0, 7.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 4.0, 0.0, 1.0]}
     ],
     "status": "Good"
}

{
    "_id": {"$oid": "62a8670192fd89ad9c4932ee"},
    "firstname": "Tahir",
    "lastname": "Raza",
    "gender": "M",
    "contact": {
        "email": "tahirraza@gmail.com",
        "phone": [
            {"type": "assistant", "number": "123478789"},
            {"type": "personal", "number": "122378369"}
         ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [4.0, 5.0, 6.0, 7.0, 4.0, 6.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 2.0, 7.0, 5.0, 2.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 1.0, 0.0, 0.0]}
     ],
     "status": "Good"
}

在这个 Java 程序中,我们使用 updateMany() 方法对匹配过滤器查询的嵌入文档执行批量更新。

在这里,我们将 contact.phone.type 的值从 official 更新为 assistant。要访问文档数组,我们使用位置运算符 ($) 来更新满足过滤器查询的第一个数组值。

在使用位置运算符时,我们还可以指定应该更新哪些数组元素。我们可以指定要更新的第一个、所有或特定的数组元素。

为了通过位置运算符指定数组元素,我们使用 dot notation,一种用于导航 BSON 对象的属性访问语法。我们通过以下方式使用位置运算符来更新第一个、所有或指定的数组元素。

  1. 我们使用位置运算符($)来更新满足过滤查询的数组的第一个元素,而数组字段必须是过滤查询的一部分才能使用位置运算符。

  2. 我们使用所有位置运算符($[])来更新数组的所有项目(元素)。

  3. 过滤位置运算符 ($[<identifier>]) 用于更新与过滤查询匹配的数组元素。在这里,我们必须在更新操作中包含数组过滤器,以告知哪些数组元素需要更新。

    请记住,<identifier> 是我们为数组过滤器指定的名称。此值必须以小写字母开头,并且只能包含字母数字字符。

使用 bulkWrite() API 更新与过滤查询匹配的现有文档

示例代码:

// write your package where you want to save your source file
package com.voidtesting.javamongobulkupdateexample;

// import necessary libraries
import com.mongodb.MongoException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.DeleteOneModel;
import com.mongodb.client.model.UpdateManyModel;
import com.mongodb.client.model.WriteModel;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;

// Example_4
public class Example_4 {
  // main method
  public static void main(String[] args) {
    // Replace the connection string with your own connection string
    var uri = "mongodb://localhost:27017";

    // try block
    try (MongoClient mongoClient = MongoClients.create(uri)) {
      // print message if connection is successfully established
      System.out.println("Connected successfully to server.");

      // get the specified database from the MongoDB server
      MongoDatabase database = mongoClient.getDatabase("bulkUpdate");

      // get the specified collection from the selected database
      MongoCollection<Document> collection = database.getCollection("supervisor");

      // create object
      List<WriteModel<Document>> writes = new ArrayList<>();

      // delete the document matching the filter
      writes.add(new DeleteOneModel<>(new Document("firstname", "Tahir")));

      // update document matching the filter
      writes.add(new UpdateManyModel<>(new Document("status", "Good"), // filter
          new Document("$set", new Document("status", "Excellent")) // update
          ));

      // bulk write
      collection.bulkWrite(writes);

      // iterate over all documents of the selected collection
      // to print in Java IDE
      collection.find().forEach(doc -> {
        System.out.println(doc.toBsonDocument());
        System.out.println();
      }); // end forEach

    } // end try block
    catch (MongoException me) {
      System.err.println("An error occurred while running a command: " + me);
    } // end catch block
  } // end main method

} // end Example_4

输出:

{
    "_id": {"$oid": "62a866e592fd89ad9c4932ed"},
    "firstname": "Mehvish",
    "lastname": "Ashiq",
    "gender": "F",
    "contact": {
        "email": "mehvishofficial@gmail.com",
        "phone": [
            {"type": "assistant", "number": "123456789"},
            {"type": "personal", "number": "124578369"}
        ]
     },
     "entries": [
         {"_id": 1.0, "itemsperday": [1.0, 3.0, 4.0, 5.0, 6.0, 7.0]},
         {"_id": 2.0, "itemperday": [2.0, 3.0, 4.0, 5.0, 2.0, 7.0]},
         {"_id": 3.0, "itemperday": [5.0, 0.0, 0.0, 4.0, 0.0, 1.0]}
     ],
     "status": "Excellent"
}

在此示例中,我们使用 bulkWrite()API 一次执行多个操作(删除和更新)。DeleteOneModel() 用于删除匹配过滤器的文档,而我们使用 UpdateManyModel() 更新所有匹配过滤器的文档中已存在字段的值。