MongoDB Java
最后修改于 2024 年 1 月 27 日
在本文中,我们将展示如何在 Java 中使用 MongoDB。ZetCode 上有一篇简明的 Java 教程。
MongoDB 是一个 NoSQL 跨平台面向文档的数据库。它是目前最流行的数据库之一。MongoDB 由 MongoDB Inc. 开发,并作为免费和开源软件发布。
MongoDB 中的一条记录就是一个文档,它是由字段和值对组成的数据结构。MongoDB 文档类似于 JSON 对象。字段的值可以包括其他文档、数组和文档数组。MongoDB 将文档存储在集合中。集合类似于关系数据库中的表,而文档类似于行。
MongoDB 在内部使用一种名为 BSON 的二进制编码格式来表示 JSON 文档。BSON 扩展了 JSON 模型,以提供额外的数据类型、有序字段,并能高效地在不同语言中进行编码和解码。.NET 驱动程序使用 BsonDocument 来表示 BSON。
安装 MongoDB
以下命令可用于在基于 Debian 的 Linux 上安装 MongoDB。
$ sudo apt-get install mongodb
该命令安装 MongoDB 附带的必要软件包。
$ sudo service mongodb status mongodb start/running, process 975
使用 sudo service mongodb status 命令,我们检查 mongodb 服务器的状态。
$ sudo service mongodb start mongodb start/running, process 6448
mongodb 服务器通过 sudo service mongodb start 命令启动。
创建数据库
mongo 工具是一个与 MongoDB 交互的 JavaScript shell 界面,它为系统管理员提供了一个接口,也为开发人员提供了一种直接与数据库测试查询和操作的方式。
$ mongo testdb
MongoDB shell version v4.0.7
connecting to: mongodb://127.0.0.1:27017/testdb?gssapiServiceName=mongodb
...
> db
testdb
> db.cars.insert({name: "Audi", price: 52642})
> db.cars.insert({name: "Mercedes", price: 57127})
> db.cars.insert({name: "Skoda", price: 9000})
> db.cars.insert({name: "Volvo", price: 29000})
> db.cars.insert({name: "Bentley", price: 350000})
> db.cars.insert({name: "Citroen", price: 21000})
> db.cars.insert({name: "Hummer", price: 41400})
> db.cars.insert({name: "Volkswagen", price: 21600})
我们创建一个 testdb 数据库,并在 cars 集合中插入八个文档。
Java MongoDB 驱动
我们使用以下 Maven 声明将 MongoDB Java 驱动程序包含在我们的项目中。
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>x.y.z</version>
</dependency>
这是一个一体化的 JAR,它嵌入了核心驱动和 BSON。BSON 是二进制 JSON(Binary JSON)的缩写,是一种对类 JSON 文档进行二进制编码的序列化格式。
Java MongoDB 列出数据库集合
第一个示例连接到 testdb 数据库并检索其集合。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>mongocommand</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.10.2</version>
</dependency>
</dependencies>
</project>
这是我们的 pom.xml 文件。
package com.zetcode;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MongoListCollections {
public static void main(String[] args) {
Logger mongoLogger = Logger.getLogger("org.mongodb.driver");
mongoLogger.setLevel(Level.SEVERE);
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
MongoDatabase database = mongoClient.getDatabase("testdb");
for (String name : database.listCollectionNames()) {
System.out.println(name);
}
}
}
}
该示例连接到 testdb 数据库并检索其所有集合。
Logger mongoLogger = Logger.getLogger("org.mongodb.driver");
mongoLogger.setLevel(Level.SEVERE);
我们为 MongoDB 设置了日志记录级别。我们只显示 SEVERE 级别的错误消息。
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
MongoClient 类用于连接到 MongoDB 服务器。它通过调用 MongoClients.create 方法创建。27017 是 MongoDB 服务器监听的默认端口。
MongoDatabase database = mongoClient.getDatabase("testdb");
通过 getDatabase 方法,我们检索 testdb 数据库。
for (String name : database.listCollectionNames()) {
System.out.println(name);
}
listCollectionNames 方法查找 testdb 数据库中的所有集合。
cars cities
在我们的数据库中,我们有两个集合。
Java MongoDB 数据库统计信息
下一个示例连接到 testdb 数据库并获取其统计信息。
package com.zetcode;
import com.mongodb.client.MongoClients;
import org.bson.Document;
import java.util.Map;
public class MongoCommand {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
var stats = database.runCommand(new Document("dbstats", 1));
for (Map.Entry<String, Object> set : stats.entrySet()) {
System.out.format("%s: %s%n", set.getKey(), set.getValue());
}
}
}
}
该示例连接到 testdb 数据库并执行 dbstats 命令。它显示了一些数据库统计信息。
var stats = database.runCommand(new Document("dbstats", 1));
我们使用 runCommand 方法执行 dbstats 命令。该命令返回一个 Document,它是 MongoDB 文档的一种映射表示形式。
for (Map.Entry<String, Object> set : stats.entrySet()) {
System.out.format("%s: %s%n", set.getKey(), set.getValue());
}
我们遍历文档的条目。
db: testdb collections: 2 views: 0 objects: 9 avgObjSize: 48.111111111111114 dataSize: 433.0 storageSize: 57344.0 numExtents: 0 indexes: 2 indexSize: 57344.0 fsUsedSize: 1.4818904064E11 fsTotalSize: 2.547211264E11 ok: 1.0
Java MongoDB 读取数据
MongoCollection 用于存储从集合返回的 mongo 文档。MongoCursor 是一个用于遍历数据库查询结果的游标。它能确保在发生异常时被关闭。
package com.zetcode;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import org.bson.Document;
import java.util.ArrayList;
public class MongoReadAll {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
try (MongoCursor<Document> cur = collection.find().iterator()) {
while (cur.hasNext()) {
var doc = cur.next();
var cars = new ArrayList<>(doc.values());
System.out.printf("%s: %s%n", cars.get(1), cars.get(2));
}
}
}
}
}
在该示例中,我们遍历 cars 集合的所有数据。
MongoCollection<Document> collection = database.getCollection("cars");
我们使用 getCollection 方法检索 cars 集合。
try (MongoCursor<Document> cur = collection.find().iterator()) {
while (cur.hasNext()) {
var doc = cur.next();
var cars = new ArrayList<>(doc.values());
System.out.printf("%s: %s%n", cars.get(1), cars.get(2));
}
}
我们遍历集合中的文档。find 方法查找集合中的所有文档。
Audi: 52642.0 Mercedes: 57127.0 Skoda: 9000.0 Volvo: 29000.0 Bentley: 350000.0 Citroen: 21000.0 Hummer: 41400.0 Volkswagen: 21600.0
Java MongoDB 查询操作符
可以使用 MongoDB 查询操作符(如 $gt、$lt 或 $ne)来过滤数据。查询操作符可以在 BasicDBObject 类中指定。
package com.zetcode;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import java.util.function.Consumer;
public class MongoReadGreaterThan {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
var query = new BasicDBObject("price",
new BasicDBObject("$gt", 30000));
collection.find(query).forEach((Consumer<Document>) doc ->
System.out.println(doc.toJson()));
}
}
}
该示例打印出所有汽车价格大于 30,000 的文档。
var query = new BasicDBObject("price",
new BasicDBObject("$gt", 30000));
我们使用 $gt 查询操作符。
collection.find(query).forEach((Consumer<Document>) doc ->
System.out.println(doc.toJson()));
forEach 方法是一个语法糖,避免了应用程序代码需要担心必须手动关闭游标。数据使用 toJson 方法以 JSON 格式打印出来。
{"_id": {"$oid": "5d4d13d6463315268eb7376b"}, "name": "Audi", "price": 52642.0}
{"_id": {"$oid": "5d4d13f5463315268eb7376c"}, "name": "Mercedes", "price": 57127.0}
{"_id": {"$oid": "5d4d140d463315268eb7376f"}, "name": "Bentley", "price": 350000.0}
{"_id": {"$oid": "5d4d1415463315268eb73771"}, "name": "Hummer", "price": 41400.0}
这是示例以 JSON 格式输出的结果。只包含了价格超过 30,000 的汽车。
Java MongoDB 工厂过滤器查询方法
Java MongoDB 驱动程序包含用于查询过滤器的工厂方法。
package com.zetcode;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import java.util.ArrayList;
import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.gt;
import static com.mongodb.client.model.Filters.lt;
public class MongoFilter {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
FindIterable fit = collection.find(and(lt("price", 50000),
gt("price", 20000))).sort(new Document("price", -1));
var docs = new ArrayList<Document>();
fit.into(docs);
for (Document doc : docs) {
System.out.println(doc);
}
}
}
}
在该示例中,我们检索价格在 20,000 到 50,000 之间的汽车。
FindIterable fit = collection.find(and(lt("price", 50000),
gt("price", 20000))).sort(new Document("price", -1));
and、gt 和 lt 是工厂过滤器方法。此外,数据还使用 sort 方法进行了排序。
Document{{_id=5d4d1415463315268eb73771, name=Hummer, price=41400.0}}
Document{{_id=5d4d1408463315268eb7376e, name=Volvo, price=29000.0}}
Document{{_id=5d4d1419463315268eb73772, name=Volkswagen, price=21600.0}}
Document{{_id=5d4d1411463315268eb73770, name=Citroen, price=21000.0}}
Java MongoDB 投影
Projections 类为所有 MongoDB 投影操作符提供了静态工厂方法。默认情况下,每个文档的所有字段都会被投影。我们可以使用 include 和 exclude 方法来确定哪些字段应该被投影到我们的输出中。
package com.zetcode;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import java.util.ArrayList;
import static com.mongodb.client.model.Projections.excludeId;
public class MongoProjection {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
FindIterable it = collection.find().projection(excludeId());
var docs = new ArrayList<Document>();
it.into(docs);
for (Document doc : docs) {
System.out.println(doc);
}
}
}
}
该示例从输出中排除了 _id 字段。
FindIterable it = collection.find().projection(excludeId());
projection 方法设置一个文档,描述所有匹配文档要返回的字段。excludeId 是 exclude("_id") 的同义词。
Document{{name=Audi, price=52642.0}}
Document{{name=Mercedes, price=57127.0}}
Document{{name=Skoda, price=9000.0}}
Document{{name=Volvo, price=29000.0}}
Document{{name=Bentley, price=350000.0}}
Document{{name=Citroen, price=21000.0}}
Document{{name=Hummer, price=41400.0}}
Document{{name=Volkswagen, price=21600.0}}
Java MongoDB 限制数据输出
limit 查询选项指定要返回的文档数量,而 skip 选项则跳过指定数量的文档。
package com.zetcode;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import java.util.function.Consumer;
public class MongoSkipLimit {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
FindIterable<Document> fit = collection.find().skip(2).limit(5);
fit.forEach((Consumer<Document>) System.out::println);
}
}
}
该示例从 testdb.cars 集合中读取数据,跳过前两个文档,并将输出限制为五个文档。
FindIterable<Document> fit = collection.find().skip(2).limit(5);
FindIterable 的 skip 方法跳过前两个文档,而 limit 方法将输出限制为五个文档。
fit.forEach((Consumer<Document>) System.out::println);
这里我们使用 Java 8 的结构来打印文档。
Document{{_id=5d4d13fb463315268eb7376d, name=Skoda, price=9000.0}}
Document{{_id=5d4d1408463315268eb7376e, name=Volvo, price=29000.0}}
Document{{_id=5d4d140d463315268eb7376f, name=Bentley, price=350000.0}}
Document{{_id=5d4d1411463315268eb73770, name=Citroen, price=21000.0}}
Document{{_id=5d4d1415463315268eb73771, name=Hummer, price=41400.0}}
Java MongoDB 创建集合
MongoDatabase 的 createCollection 方法在数据库中创建一个新集合。MongoCollection 的 insertMany 方法向集合中插入一个或多个文档。
package com.zetcode;
import com.mongodb.MongoCommandException;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import java.util.ArrayList;
public class MongoCreateCollection {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
try {
database.createCollection("cars");
} catch (MongoCommandException e) {
database.getCollection("cars").drop();
}
var docs = new ArrayList<Document>();
MongoCollection<Document> collection = database.getCollection("cars");
var d1 = new Document("_id", 1);
d1.append("name", "Audi");
d1.append("price", 52642);
docs.add(d1);
var d2 = new Document("_id", 2);
d2.append("name", "Mercedes");
d2.append("price", 57127);
docs.add(d2);
var d3 = new Document("_id", 3);
d3.append("name", "Skoda");
d3.append("price", 9000);
docs.add(d3);
var d4 = new Document("_id", 4);
d4.append("name", "Volvo");
d4.append("price", 29000);
docs.add(d4);
var d5 = new Document("_id", 5);
d5.append("name", "Bentley");
d5.append("price", 350000);
docs.add(d5);
var d6 = new Document("_id", 6);
d6.append("name", "Citroen");
d6.append("price", 21000);
docs.add(d6);
var d7 = new Document("_id", 7);
d7.append("name", "Hummer");
d7.append("price", 41400);
docs.add(d7);
var d8 = new Document("_id", 8);
d8.append("name", "Volkswagen");
d8.append("price", 21600);
docs.add(d8);
collection.insertMany(docs);
}
}
}
该示例创建了一个 cars 集合,并向其中插入了九个文档。
try {
database.createCollection("cars");
} catch (MongoCommandException e) {
database.getCollection("cars").drop();
}
使用 createCollection 方法创建一个新集合。如果该集合已经存在,则会被删除。
MongoCollection<Document> collection = database.getCollection("cars");
使用 getCollection 方法创建一个文档的 MongoCollection。
var d1 = new Document("_id", 1);
d1.append("name", "Audi");
d1.append("price", 52642);
docs.add(d1);
创建一个新的 Document。它包含有关汽车的信息——其 ID、名称和价格。
collection.insertMany(docs);
使用 insertMany 方法将文档写入集合。
Java MongoDB 从 JSON 创建集合
JSON 类有用于解析 JSON 文档的方法。JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。它易于人类阅读和编写。
package com.zetcode;
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.bson.types.ObjectId;
public class MongoCollectionFromJSON {
public static void main(String[] args) {
try (var mongoClient = MongoClients.create("mongodb://:27017")) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("continents");
var africa = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Africa'}");
var asia = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Asia'}");
var europe = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Europe'}");
var america = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'America'}");
var australia = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Australia'}");
var antarctica = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Antarctica'}");
collection.insertOne(new Document(africa));
collection.insertOne(new Document(asia));
collection.insertOne(new Document(europe));
collection.insertOne(new Document(america));
collection.insertOne(new Document(australia));
collection.insertOne(new Document(antarctica));
}
}
}
该示例从 JSON 数据创建一个 continents 集合。
var africa = BasicDBObject.parse("{_id : '" + ObjectId.get() + "', name : 'Africa'}");
JSON 数据使用 BasicDBObject.parse 方法进行解析。
collection.insertOne(new Document(africa));
将 BasicDBObject 传递给 Document,并使用 insertOne 方法将其插入到集合中。
> db.continents.find()
{ "_id" : "5d4af89645ffb636567b6448", "name" : "Africa" }
{ "_id" : "5d4af89645ffb636567b6449", "name" : "Asia" }
{ "_id" : "5d4af89645ffb636567b644a", "name" : "Europe" }
{ "_id" : "5d4af89645ffb636567b644b", "name" : "America" }
{ "_id" : "5d4af89645ffb636567b644c", "name" : "Australia" }
{ "_id" : "5d4af89645ffb636567b644d", "name" : "Antarctica" }
我们使用 mongo 来显示创建的集合。
Java MongoDB 修改文档
MongoCollection 的 deleteOne 方法用于删除文档,updateOne 用于更新文档。
package com.zetcode;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import static com.mongodb.client.model.Filters.eq;
public class MongoModify {
public static void main(String[] args) {
try (var mongoClient = new MongoClient("localhost", 27017)) {
var database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("cars");
collection.deleteOne(eq("name", "Skoda"));
collection.updateOne(new Document("name", "Audi"),
new Document("$set", new Document("price", 52000)));
}
}
}
该示例删除包含 Skoda 的文档并更新 Audi 的价格。
collection.deleteOne(eq("name", "Skoda"));
deleteOne 删除 Skoda 的文档。eq 创建一个过滤器,匹配字段名值等于指定值的所有文档。
collection.updateOne(new Document("name", "Audi"),
new Document("$set", new Document("price", 52000)));
使用 updateOne 方法将 Audi 的价格更改为 52,000。
> db.cars.find()
{ "_id" : ObjectId("5d4d13d6463315268eb7376b"), "name" : "Audi", "price" : 52000 }
{ "_id" : ObjectId("5d4d13f5463315268eb7376c"), "name" : "Mercedes", "price" : 57127 }
{ "_id" : ObjectId("5d4d1408463315268eb7376e"), "name" : "Volvo", "price" : 29000 }
{ "_id" : ObjectId("5d4d140d463315268eb7376f"), "name" : "Bentley", "price" : 350000 }
{ "_id" : ObjectId("5d4d1411463315268eb73770"), "name" : "Citroen", "price" : 21000 }
{ "_id" : ObjectId("5d4d1415463315268eb73771"), "name" : "Hummer", "price" : 41400 }
{ "_id" : ObjectId("5d4d1419463315268eb73772"), "name" : "Volkswagen", "price" : 21600 }
我们使用 mongo 工具确认更改。
来源
在本文中,我们学习了如何结合使用 MongoDB 和 Java。
作者
列出所有Java教程。