写入操作
您可以对集合执行写入操作以插入新文档、更新现有文档、替换现有文档或删除现有文档。
先决条件
您必须设置以下组件才能运行本指南中的代码示例
A
test.restaurants
集合,该集合包含从文档restaurants.json
中获取的文档,该文档位于文档资源 GitHub.以下导入语句
import com.mongodb.*; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Updates.*; import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.result.*; import org.bson.Document; import org.bson.types.ObjectId; import java.util.List; import java.util.Arrays; import java.util.ArrayList;
重要
本指南使用 Subscriber
实现,这些实现已在快速入门指南中描述中.
连接到 MongoDB 部署
首先,连接到 MongoDB 部署,然后声明并定义 MongoDatabase
和 MongoCollection
实例。
以下代码连接到在 localhost
上运行并监听 27017
端口的独立 MongoDB 部署。然后,它定义 database
变量以引用 test
数据库,以及 collection
变量以引用 restaurants
集合
MongoClient mongoClient = MongoClients.create(); MongoDatabase database = mongoClient.getDatabase("test"); MongoCollection<Document> collection = database.getCollection("restaurants");
有关连接到 MongoDB 部署的更多信息,请参阅连接到 MongoDB 指南。
插入文档
要将单个文档插入到集合中,您可以使用集合的 insertOne()
方法
Document document = new Document("name", "Café Con Leche") .append("contact", new Document("phone", "228-555-0149") .append("email", "cafeconleche@example.com") .append("location",Arrays.asList(-73.92502, 40.8279556))) .append("stars", 3) .append("categories", Arrays.asList("Bakery", "Coffee", "Pastries")); collection.insertOne(document).subscribe(new ObservableSubscriber<Void>());
注意
如果文档中没有指定顶级 id
字段,MongoDB 会自动生成一个值,并将此字段添加到插入的文档中。
插入多个文档
要插入多个文档,可以使用集合的 insertMany()
方法,该方法接受一个要插入的文档列表作为参数。
以下示例将两个文档插入集合中
Document doc1 = new Document("name", "Amarcord Pizzeria") .append("contact", new Document("phone", "264-555-0193") .append("email", "amarcord.pizzeria@example.net") .append("location",Arrays.asList(-73.88502, 40.749556))) .append("stars", 2) .append("categories", Arrays.asList("Pizzeria", "Italian", "Pasta")); Document doc2 = new Document("name", "Blue Coffee Bar") .append("contact", new Document("phone", "604-555-0102") .append("email", "bluecoffeebar@example.com") .append("location",Arrays.asList(-73.97902, 40.8479556))) .append("stars", 5) .append("categories", Arrays.asList("Coffee", "Pastries")); List<Document> documents = new ArrayList<Document>(); documents.add(doc1); documents.add(doc2); collection.insertMany(documents).subscribe(new ObservableSubscriber<Void>());;
注意
如果文档中没有指定顶级 id
字段,MongoDB 会自动生成一个值,并将此字段添加到插入的文档中。
更新现有文档
要更新集合中的现有文档,可以使用集合的 updateOne()
或 updateMany()
方法。
过滤器
可以将过滤器文档传递给方法以指定要更新的文档。过滤器文档的指定与读取操作相同。为了方便创建过滤器对象,驱动程序提供了 Filters
辅助类。
要指定空过滤器并匹配集合中的所有文档,请使用空 Document
对象作为过滤器。
更新运算符
要更改文档中的字段,MongoDB 提供了更新运算符。要使用更新运算符指定要执行的修改,请创建一个更新文档。有关更新运算符的更多信息,请参阅服务器手册中的更新运算符。
为了方便创建更新文档,驱动程序提供了 Updates
辅助类。
重要
id
字段是不可变的,因此您不能更改文档中 id
字段的值。
更新单个文档
updateOne()
方法更新单个文档,即使筛选条件与集合中的多个文档匹配。
以下对 restaurants
集合的操作更新了 id
字段值为 ObjectId("57506d62f57802807471dd41")
的文档。
collection.updateOne( eq("_id", new ObjectId("57506d62f57802807471dd41")), combine(set("stars", 1), set("contact.phone", "228-555-9999"), currentDate("lastModified")) ).subscribe(new ObservableSubscriber<UpdateResult>());
具体来说,操作使用了以下方法
Updates.set()
将stars
字段的值设置为1
和contact.phone
字段的值为"228-555-9999"
Updates.currentDate()
将lastModified
字段修改为当前日期。如果lastModified
字段不存在,则运算符会将该字段添加到文档中。
更新多个文档
updateMany()
方法更新所有匹配过滤器条件的文档。
以下对 restaurants
集合的操作更新了所有 stars
字段值为 2
的文档
collection.updateMany( eq("stars", 2), combine(set("stars", 0), currentDate("lastModified")) ).subscribe(new ObservableSubscriber<UpdateResult>());
具体来说,操作使用了以下方法
Updates.set()
将stars
字段的值设置为0
Updates.currentDate()
将lastModified
字段设置为当前日期。如果lastModified
字段不存在,操作符将字段添加到文档中。
更新选项
当使用 updateOne()
和 updateMany()
方法时,您可以在 UpdateOptions
文档中包含 upsert
选项或 bypassDocumentationValidation
选项
collection.updateOne( eq("_id", 1), combine(set("name", "Fresh Breads and Tulips"), currentDate("lastModified")), new UpdateOptions().upsert(true).bypassDocumentValidation(true) ).subscribe(new ObservableSubscriber<UpdateResult>());
替换现有文档
要替换集合中的现有文档,您可以使用集合的 replaceOne()
方法。
重要
id
字段是不可变的,因此您不能在文档中替换id
字段。
过滤器
您可以将过滤器文档传递给replaceOne()
方法来指定要替换哪个文档。过滤器文档的指定与读取操作相同。为了方便创建过滤器对象,驱动程序提供了Filters
辅助类。
要指定空过滤器并匹配集合中的所有文档,请使用空 Document
对象作为过滤器。
replaceOne()
方法最多替换一个文档,即使过滤器条件与集合中的多个文档匹配。
替换文档
要替换文档,请将新文档传递给replaceOne()
方法。
重要
替换文档可以包含与原始文档不同的字段。在替换文档中,由于id
字段是不可变的,因此您可以省略id
字段。但是,如果您包含id
字段,则不能为id
字段指定不同的值。
以下对restaurants
集合的操作替换了id
字段值为ObjectId("57506d62f57802807471dd41")
的文档
collection.replaceOne( eq("_id", new ObjectId("57506d62f57802807471dd41")), new Document("name", "Green Salads Buffet") .append("contact", "TBD") .append("categories", Arrays.asList("Salads", "Health Foods", "Buffet")) ).subscribe(new ObservableSubscriber<UpdateResult>());
更新选项
当使用replaceOne()
方法时,您可以包含一个UpdateOptions
文档来指定upsert
选项或bypassDocumentationValidation
选项。
collection.replaceOne( eq("name", "Orange Patisserie and Gelateria"), new Document("stars", 5) .append("contact", "TBD") .append("categories", Arrays.asList("Cafe", "Pastries", "Ice Cream")), new UpdateOptions().upsert(true).bypassDocumentValidation(true) ).subscribe(new ObservableSubscriber<UpdateResult>());
删除文档
要删除集合中的文档,可以使用 deleteOne()
和 deleteMany()
方法。
过滤器
您可以将过滤器文档传递给这些方法以指定要删除的文档。过滤器文档的指定方式与读取操作相同。为了便于创建过滤器对象,驱动程序提供了 Filters
辅助类。
要指定空过滤器并匹配集合中的所有文档,请使用空 Document
对象作为过滤器。
删除单个文档
deleteOne()
方法最多删除单个文档,即使过滤器条件与集合中的多个文档匹配。
以下对 restaurants
集合的操作将删除具有 _id
字段值为 ObjectId("57506d62f57802807471dd41")
的文档。
collection .deleteOne(eq("_id", new ObjectId("57506d62f57802807471dd41"))) .subscribe(new ObservableSubscriber<DeleteResult>());
删除多个文档
deleteMany()
方法删除所有匹配过滤条件的文档。
以下对 restaurants
集合的操作删除了所有 stars
字段值为 4
的文档。
collection .deleteMany(eq("stars", 4)) .subscribe(new ObservableSubscriber<DeleteResult>());
写关注
写关注描述了 MongoDB 对写操作请求的确认级别。
您可以在以下级别配置写关注
在以下方式中配置
MongoClient
通过创建
MongoClientSettings
实例MongoClient mongoClient = MongoClients.create(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://host1,host2")) .writeConcern(WriteConcern.MAJORITY) .build()); 通过创建
ConnectionString
实例MongoClient mongoClient = MongoClients.create("mongodb://host1:27017,host2:27017/?w=majority");
通过使用
withWriteConcern()
方法在MongoDatabase
中MongoDatabase database = mongoClient.getDatabase("test").withWriteConcern(WriteConcern.MAJORITY); 通过使用
withWriteConcern()
方法在MongoCollection
中MongoCollection<Document> collection = database .getCollection("restaurants") .withWriteConcern(WriteConcern.MAJORITY);
MongoDatabase
和 MongoCollection
实例是不可变的。在现有的 MongoDatabase
或 MongoCollection
实例上调用 withWriteConcern()
会返回一个新的实例,并且不会影响调用方法时的实例。
在以下示例中,collWithWriteConcern
实例的写关注为 majority
,而集合的读偏好不受影响
MongoCollection<Document> collWithWriteConcern = collection .withWriteConcern(WriteConcern.MAJORITY);
您可以将 MongoClientSettings
、MongoDatabase
或 MongoCollection
实例构建为包括读取关注、读取偏好和写关注的组合。
例如,以下代码在集合级别设置了所有三个
Collection = database.getCollection("restaurants") .withReadPreference(ReadPreference.primary()) .withReadConcern(ReadConcern.MAJORITY) .withWriteConcern(WriteConcern.MAJORITY);