1. 简介

本文将介绍 MongoDB 中的核心概念之一 —— BSON,以及如何使用 Java 驱动通过 BSON 与 MongoDB 进行交互。

虽然本文不会深入讲解 MongoDB 的全部功能,但我们会介绍一些关键概念。MongoDB 是一个分布式的 NoSQL 文档存储引擎,文档以 BSON 格式存储,并组织在集合中。集合中的文档类似于关系型数据库中的行

如果你对 MongoDB 的整体架构和使用方式感兴趣,可以参考我们之前的 MongoDB 入门教程

2. 什么是 BSON?

BSON 是 Binary JSON 的缩写,是一种用于序列化 JSON 类型数据的二进制协议。

JSON 是现代 Web 服务中广泛使用的数据交换格式,它提供了一种灵活的方式来表示复杂的数据结构。相比 JSON,BSON 提供了以下优势:

更紧凑:在大多数情况下,BSON 比等效的 JSON 占用更少的存储空间
支持更多数据类型:如 DateBinData 等 JSON 不支持的类型
易于遍历:BSON 文档中包含额外的元信息,便于直接定位和修改字段,而无需解析整个文档

这些特性使得 BSON 成为 MongoDB 的理想存储格式。

3. MongoDB Java 驱动

我们已经了解了 BSON 的基本概念,现在来看看如何使用 MongoDB Java 驱动通过 BSON 进行 CRUD 操作(即 Create、Read、Update、Delete)。

MongoDB 提供了多种语言的官方驱动,这些驱动都基于 BSON 库构建,因此我们使用驱动时,本质上就是在操作 BSON 数据结构。

⚠️ 本文主要介绍直接使用 BSON API 的方式。如果你希望使用更高级的封装,比如 Spring Data MongoDB,可以参考我们的 Spring Data MongoDB 教程

3.1. 建立连接

首先,添加 MongoDB Java 驱动依赖:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.8.2</version>
</dependency>

然后使用 Java 代码连接数据库和集合:

MongoClient mongoClient = MongoClients.create();
MongoDatabase database = mongoClient.getDatabase("myDB");
MongoCollection<Document> collection = database.getCollection("employees");

接下来我们将使用 collection 引用进行各种操作。

3.2. 插入文档

假设我们要插入如下 JSON 数据到 employees 集合中:

{
  "first_name" : "Joe",
  "last_name" : "Smith",
  "title" : "Java Developer",
  "years_of_service" : 3,
  "skills" : ["java","spring","mongodb"],
  "manager" : {
     "first_name" : "Sally",
     "last_name" : "Johanson"
  }
}

使用 Java 的 Document 类可以轻松构建 BSON 文档并插入:

Document employee = new Document()
    .append("first_name", "Joe")
    .append("last_name", "Smith")
    .append("title", "Java Developer")
    .append("years_of_service", 3)
    .append("skills", Arrays.asList("java", "spring", "mongodb"))
    .append("manager", new Document()
        .append("first_name", "Sally")
        .append("last_name", "Johanson"));
collection.insertOne(employee);

Document 类继承自 Java 的 Map 接口,支持丰富的类型操作,包括嵌套文档、数组等。

3.3. 查询文档

MongoDB 查询文档通过构建一个“查询条件”文档来实现。例如,查找所有姓氏为 "Smith" 的员工:

{  
  "last_name": "Smith"
}

对应的 Java 代码如下:

Document query = new Document("last_name", "Smith");
List<Document> results = new ArrayList<>();
collection.find(query).into(results);

默认情况下,多个查询条件之间是 AND 关系,即必须全部匹配。若想使用 OR 查询,可以这样写:

{
  "$or": [
    { "first_name": "Joe" },
    { "last_name":"Smith" }
  ]
}

对应的 Java 代码如下:

Document query = new Document("$or", Arrays.asList(
    new Document("last_name", "Smith"),
    new Document("first_name", "Joe")));
List<Document> results = new ArrayList<>();
collection.find(query).into(results);

3.4. 更新文档

MongoDB 的更新操作需要两个文档:

  1. 查询条件文档
  2. 更新操作文档

例如,给所有拥有 "spring" 技能的员工添加一个新的 "security" 技能:

对应的 JSON 查询条件和更新操作如下:

{
  "skills": { 
    "$elemMatch":  { 
      "$eq": "spring"
    }
  }
}

{
  "$push": { 
    "skills": "security"
  }
}

对应的 Java 代码:

Document query = new Document(
  "skills",
  new Document(
    "$elemMatch",
    new Document("$eq", "spring")));
Document update = new Document(
  "$push",
  new Document("skills", "security"));
collection.updateMany(query, update);

3.5. 删除文档

删除文档的语法与查询类似,只需要传入匹配条件即可。

例如,删除 years_of_service 为负数的员工:

{
  "years_of_service" : { 
    "$lt" : 0
  }
}

对应的 Java 代码如下:

Document query = new Document(
  "years_of_service", 
  new Document("$lt", 0));
collection.deleteMany(query);

4. 总结

本文我们介绍了如何使用 MongoDB 的 Java 驱动和 BSON API 实现基本的 CRUD 操作。通过 Document 类,我们可以灵活地构建和操作 BSON 数据结构。

虽然本文没有涉及投影(Projection)、聚合(Aggregation)、地理空间查询等高级特性,但这些功能都可以通过 BSON API 实现。掌握本文中的基础操作,是实现这些高级功能的前提。

完整示例代码可以在我们的 GitHub 仓库 中找到。


原始标题:MongoDB BSON Guide | Baeldung