MongoDB初学者教程:从零开始掌握MongoDB(第二阶段:CRUD基础操作)

19 阅读7分钟

MongoDB初学者教程:从零开始掌握MongoDB(第二阶段:CRUD基础操作)

欢迎回到MongoDB的学习之旅!在第一阶段,我们了解了MongoDB的基本概念(NoSQL、文档型数据库、BSON格式),并完成了环境搭建和Java项目初始化。现在,我们进入第二阶段:CRUD基础操作,这是MongoDB的核心技能——如何在数据库中增删改查数据。

CRUD是什么?它代表:

  • Create(创建):向数据库添加新数据。
  • Read(读取):从数据库查询数据。
  • Update(更新):修改数据库中的数据。
  • Delete(删除):删除数据库中的数据。

本阶段将带你掌握MongoDB的文档操作(插入、查询、更新、删除),并通过Java驱动实现这些操作。你将学会用代码和MongoDB“对话”,像管理一个智能文件夹一样管理数据。本阶段约4000字,包含大量示例代码和实践步骤,适合零基础的你!

第二阶段:CRUD基础操作

一、基础文档操作

MongoDB的核心是文档(Document),类似于JSON格式的数据。文档存储在集合(Collection)中,集合就像一个文件夹,文档就像文件夹里的文件。我们的任务是用MongoDB的命令或Java代码,在这些“文件夹”里增删改查“文件”。

我们将使用MongoDB的命令行工具(mongosh)或MongoDB Compass来演示操作,同时结合Java代码实现。假设你已经安装了MongoDB社区版(参考第一阶段),并且有一个名为mydb的数据库,里面有一个users集合。

1. 插入文档(insertOne/insertMany)

插入文档就是往集合里添加新数据,就像往文件夹里放一张新便签。

用MongoDB命令插入

mongosh中,连接到MongoDB(运行mongosh),切换到mydb数据库:

use mydb

插入单个文档(insertOne)

db.users.insertOne({
  "name": "小明",
  "age": 20,
  "city": "北京"
})

输出会显示插入成功的提示,包含文档的_id(MongoDB自动生成的主键):

{
  "acknowledged": true,
  "insertedId": ObjectId("671234567890123456789012")
}

插入多个文档(insertMany)

db.users.insertMany([  {    "name": "小红",    "age": 22,    "city": "上海"  },  {    "name": "小刚",    "age": 25,    "city": "广州",    "hobbies": ["读书", "旅行"]
  }
])

输出会显示多个_id

{
  "acknowledged": true,
  "insertedIds": {
    "0": ObjectId("671234567890123456789013"),
    "1": ObjectId("671234567890123456789014")
  }
}
用Compass插入

在MongoDB Compass中:

  1. 打开mydb数据库,点击users集合。
  2. 点击“Add Data” -> “Insert Document”。
  3. 输入JSON格式的文档(比如{"name": "小明", "age": 20}),点击“Insert”。
  4. 刷新集合,查看新插入的数据。

生活化比喻insertOne就像往文件夹里放一张便签,insertMany是把一叠便签一次性塞进去。MongoDB会自动给每张便签贴上一个唯一标签(_id)。

2. 查询文档(find/findOne)

查询文档是从集合中查找数据,就像在文件夹里翻找特定便签。

用MongoDB命令查询

查询单个文档(findOne)

db.users.findOne({"name": "小明"})

输出:

{
  "_id": ObjectId("671234567890123456789012"),
  "name": "小明",
  "age": 20,
  "city": "北京"
}

查询多个文档(find)

db.users.find({"city": "上海"})

输出(可能有多条):

{
  "_id": ObjectId("671234567890123456789013"),
  "name": "小红",
  "age": 22,
  "city": "上海"
}

find()时,可以加.pretty()让输出更美观:

db.users.find().pretty()

查询条件

  • 精确匹配:{"age": 20}
  • 范围查询:{"age": {"$gt": 20}}(大于20)
  • 数组包含:{"hobbies": "读书"}
用Compass查询
  1. users集合界面,点击“Filter”栏。
  2. 输入查询条件(比如{"name": "小明"}),点击“Find”。
  3. 查看匹配的文档。

生活化比喻findOne是在文件夹里找到第一张写着“小明”的便签就停下来;find是把所有符合条件的便签都拿出来。

3. 更新文档(updateOne/updateMany)

更新文档是修改集合中的数据,就像在便签上改写内容。

用MongoDB命令更新

更新单个文档(updateOne)
把小明的年龄改为21:

db.users.updateOne(
  {"name": "小明"},
  {"$set": {"age": 21}}
)

输出:

{
  "acknowledged": true,
  "matchedCount": 1,
  "modifiedCount": 1
}
  • {"name": "小明"}:匹配条件。
  • {"$set": {"age": 21}}:更新操作,$set表示修改字段。

更新多个文档(updateMany)
把所有年龄大于20的用户城市改为“深圳”:

db.users.updateMany(
  {"age": {"$gt": 20}},
  {"$set": {"city": "深圳"}}
)

输出:

{
  "acknowledged": true,
  "matchedCount": 2,
  "modifiedCount": 2
}
用Compass更新
  1. users集合中找到目标文档。
  2. 点击“Edit Document”,修改字段(比如把age改为21)。
  3. 点击“Update”保存。

生活化比喻updateOne是改一张便签的内容,updateMany是把一堆符合条件的便签都改一遍。

4. 删除文档(deleteOne/deleteMany)

删除文档是从集合中移除数据,就像扔掉不需要的便签。

用MongoDB命令删除

删除单个文档(deleteOne)
删除小明的文档:

db.users.deleteOne({"name": "小明"})

输出:

{
  "acknowledged": true,
  "deletedCount": 1
}

删除多个文档(deleteMany)
删除所有城市为“深圳”的用户:

db.users.deleteMany({"city": "深圳"})

输出:

{
  "acknowledged": true,
  "deletedCount": 2
}
用Compass删除
  1. users集合中找到目标文档。
  2. 点击“Delete Document”(垃圾桶图标),确认删除。

生活化比喻deleteOne是扔掉一张便签,deleteMany是把一堆符合条件的便签都扔掉。

二、Java驱动基础使用

现在,我们将用Java代码实现上述CRUD操作,基于第一阶段创建的Maven项目(包含MongoDB Java驱动)。我们会学习如何连接MongoDB、操作集合,以及将Java对象(POJO)与MongoDB文档相互转换。

1. MongoClient连接配置

在第一阶段,我们用以下代码连接了MongoDB:

MongoClient client = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = client.getDatabase("mydb");

为了更灵活,我们可以配置连接参数,比如超时时间、连接池大小。以下是一个更完整的连接示例:

import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;

public class MongoDBConnection {
    public static MongoClient connect() {
        ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017");
        MongoClientSettings settings = MongoClientSettings.builder()
                .applyConnectionString(connectionString)
                .build();
        return MongoClients.create(settings);
    }
}

保存这个类,之后可以重复使用connect()方法获取MongoClient

2. 使用MongoCollection进行CRUD

我们将用MongoCollection操作users集合,实现CRUD。以下是完整示例代码。

准备工作
创建一个Java类UserCRUDSample,包含所有CRUD操作:

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

public class UserCRUDSample {
    private final MongoCollection<Document> users;

    public UserCRUDSample(MongoClient client) {
        MongoDatabase database = client.getDatabase("mydb");
        users = database.getCollection("users");
    }
}

插入文档

public void insertUser() {
    // 插入单个文档
    Document user1 = new Document("name", "小明")
            .append("age", 20)
            .append("city", "北京");
    users.insertOne(user1);
    System.out.println("Inserted user: 小明");

    // 插入多个文档
    List<Document> userList = Arrays.asList(
            new Document("name", "小红").append("age", 22).append("city", "上海"),
            new Document("name", "小刚").append("age", 25).append("city", "广州")
                    .append("hobbies", Arrays.asList("读书", "旅行"))
    );
    users.insertMany(userList);
    System.out.println("Inserted multiple users");
}

查询文档

public void findUsers() {
    // 查询单个文档
    Document user = users.find(new Document("name", "小明")).first();
    System.out.println("Found user: " + user.toJson());

    // 查询多个文档
    FindIterable<Document> results = users.find(new Document("city", "上海"));
    for (Document doc : results) {
        System.out.println("Found user in 上海: " + doc.toJson());
    }
}

更新文档

public void updateUsers() {
    // 更新单个文档
    users.updateOne(
            new Document("name", "小明"),
            new Document("$set", new Document("age", 21))
    );
    System.out.println("Updated 小明's age");

    // 更新多个文档
    users.updateMany(
            new Document("age", new Document("$gt", 20)),
            new Document("$set", new Document("city", "深圳"))
    );
    System.out.println("Updated users' city to 深圳");
}

删除文档

public void deleteUsers() {
    // 删除单个文档
    users.deleteOne(new Document("name", "小明"));
    System.out.println("Deleted 小明");

    // 删除多个文档
    users.deleteMany(new Document("city", "深圳"));
    System.out.println("Deleted users in 深圳");
}

主程序

public static void main(String[] args) {
    MongoClient client = MongoDBConnection.connect();
    UserCRUDSample crud = new UserCRUDSample(client);

    crud.insertUser();
    crud.findUsers();
    crud.updateUsers();
    crud.deleteUsers();

    client.close();
}

运行这个程序,你会看到MongoDB的CRUD操作结果。确保MongoDB服务(mongod)已启动。

3. POJO与Document转换

在实际开发中,我们通常用Java对象(POJO,Plain Old Java Object)表示数据,而不是直接操作Document。MongoDB Java驱动支持POJO与文档的转换。

定义POJO
创建一个User类:

public class User {
    private String id;
    private String name;
    private int age;
    private String city;
    private List<String> hobbies;

    // 构造函数
    public User(String name, int age, String city) {
        this.name = name;
        this.age = age;
        this.city = city;
    }

    // Getter和Setter
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public List<String> getHobbies() { return hobbies; }
    public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }
}

使用POJO操作
MongoDB驱动需要Codec来转换POJO和文档。我们可以用MongoCollection<User>直接操作User对象:

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;

public class UserPOJOSample {
    private final MongoCollection<User> users;

    public UserPOJOSample(MongoClient client) {
        CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
        );
        MongoDatabase database = client.getDatabase("mydb").withCodecRegistry(pojoCodecRegistry);
        users = database.getCollection("users", User.class);
    }

    public void insertUser() {
        User user = new User("小明", 20, "北京");
        users.insertOne(user);
        System.out.println("Inserted POJO user: 小明");
    }

    public void findUser() {
        User user = users.find(Filters.eq("name", "小明")).first();
        System.out.println("Found POJO user: " + user.getName() + ", " + user.getAge());
    }

    public void updateUser() {
        users.updateOne(
                Filters.eq("name", "小明"),
                Updates.set("age", 21)
        );
        System.out.println("Updated POJO user's age");
    }

    public void deleteUser() {
        users.deleteOne(Filters.eq("name", "小明"));
        System.out.println("Deleted POJO user");
    }

    public static void main(String[] args) {
        MongoClient client = MongoDBConnection.connect();
        UserPOJOSample pojoSample = new UserPOJOSample(client);

        pojoSample.insertUser();
        pojoSample.findUser();
        pojoSample.updateUser();
        pojoSample.deleteUser();

        client.close();
    }
}

说明

  • PojoCodecProvider自动将User对象与MongoDB文档映射。
  • FiltersUpdates提供了更简洁的查询和更新语法。
  • POJO让代码更符合面向对象编程习惯,适合复杂项目。

下一步是什么?

恭喜你掌握了MongoDB的CRUD操作!你学会了用命令和Java代码插入、查询、更新、删除文档,还能用POJO优雅地操作数据。这些技能是MongoDB开发的基础,就像学会了管理一个智能文件夹的“增删改查”。

后续阶段我们将深入:

  • 第三阶段:Java开发实践(Spring Boot集成、REST API实现,约4000字)
  • 第四阶段:进阶与优化(索引、聚合、分布式部署,约4000字)
  • 第五阶段:实战项目(开发一个完整的Web应用,约5000字)

这些阶段将基于本阶段的代码,逐步构建一个真实项目。继续加油,你离成为MongoDB高手又近了一步!