在 MongoDB 的 CRUD 操作中使用日期

1. 概述

在本教程中,我们将使用 MongoDB Java Driver 来执行与日期相关的 CRUD 操作,例如创建和更新带有日期字段的文档,以及查询, 更新和删除日期字段在给定范围内的文档。

2. 设置

在深入实施之前,让我们设置我们的工作环境。

2.1. Maven 依赖

首先,您应该安装了 MongoDB。 如果您不这样做,您可以按照官方 MongoDB 安装 指南 进行操作。

接下来,让我们将 MongoDB Java 驱动程序 作为依赖项添加到我们的 pom.xml 文件中:

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

2.2. POJO 数据模型

让我们定义一个 POJO 来表示我们数据库中包含的文档:

public class Event {
    private String title;
    private String location;
    private LocalDateTime dateTime;

    public Event() {}
    public Event(String title, String location, LocalDateTime dateTime) {
        this.title = title;
        this.location = location;
        this.dateTime = dateTime;
    }
    
    // standard setters and getters
}

请注意,我们已经声明了两个构造函数。 MongoDB 使用无参数构造函数默认。 在本教程中,另一个构造函数供我们自己使用。

我们还要注意,虽然 dateTime 可能是 String 变量,但最佳实践是对日期字段使用特定于日期/时间的 JDK 类。 使用 String 字段来表示日期需要额外的努力来确保值的格式正确。

我们现在准备将客户端连接到我们的数据库。

2.3. MongoDB 客户端

为了让 MongoDB 序列化/反序列化我们的 Event POJO,我们需要向 MongoDB 的 CodecRegistry 注册 PojoCodecProvider

CodecProvider codecProvider = PojoCodecProvider.builder().automatic(true).build();
CodecRegistry codecRegistry = fromRegistries(getDefaultCodecRegistry(), fromProviders(codecProvider));

让我们创建一个将使用我们注册的 PojoCodecProvider 的数据库、集合和客户端:

MongoClient mongoClient = MongoClients.create(uri);
MongoDatabase db = mongoClient.getDatabase("calendar").withCodecRegistry(codecRegistry);
MongoCollection<Event> collection = db.getCollection("my_events", Event.class);

我们现在已准备好创建文档并执行与日期相关的 CRUD 操作。

3. 创建带有日期字段的文档

在我们的 POJO 中,我们使用 LocalDateTime 而不是 String,以便更轻松地处理日期值。 现在让我们利用 LocalDateTime 的便捷 API 构造 Event 对象来利用它:

Event pianoLessonsEvent = new Event("Piano lessons", "Foo Blvd",
  LocalDateTime.of(2022, 6, 4, 11, 0, 0));
Event soccerGameEvent = new Event("Soccer game", "Bar Avenue",
  LocalDateTime.of(2022, 6, 10, 17, 0, 0));

我们可以将新的 Events 插入到我们的数据库中,如下所示:

InsertOneResult pianoLessonsInsertResult = collection.insertOne(pianoLessonsEvent);
InsertOneResult soccerGameInsertResult = collection.insertOne(soccerGameEvent);

让我们通过检查插入文档的 id 来验证插入是否成功:

assertNotNull(pianoLessonsInsertResult.getInsertedId());
assertNotNull(soccerGameInsertResult.getInsertedId());

4. 查询符合日期条件的文档

现在我们的数据库中有 Events,让我们根据它们的日期字段检索它们。

我们可以使用相等过滤器 (eq) 来检索与特定日期和时间匹配的文档:

LocalDateTime dateTime = LocalDateTime.of(2022, 6, 10, 17, 0, 0);
Event event = collection.find(Filters.eq("dateTime", dateTime)).first();

让我们检查生成的 Event 的各个字段:

assertEquals("Soccer game", event.title);
assertEquals("Bar Avenue", event.location);
assertEquals(dateTime, event.dateTime);

我们还可以使用 MongoDB BasicDBObject 类以及 gtelte 运算符来使用日期范围构建更复杂的查询:

LocalDateTime from = LocalDateTime.of(2022, 06, 04, 12, 0, 0);
LocalDateTime to = LocalDateTime.of(2022, 06, 10, 17, 0, 0);

BasicDBObject object = new BasicDBObject();
object.put("dateTime", BasicDBObjectBuilder.start("$gte", from).add("$lte", to).get());

List<Event> events = collection.find(object, Event.class).into(new ArrayList<Event>());

由于足球比赛是我们查询的日期范围内唯一的 Event,我们应该在 list 中只看到一个 Event 对象,不包括钢琴课:

assertEquals(1, events.size());
assertEquals("Soccer game", events.get(0).title);
assertEquals("Bar Avenue", events.get(0).location);
assertEquals(dateTime, events.get(0).dateTime);

5. 更新文档

让我们探索两个基于日期字段更新文档的用例。 首先,我们将更新单个文档的日期字段,然后我们将更新与日期范围匹配的多个文档。

5.1. 更新文档的日期字段

要更新 MongoDB 文档,我们可以使用 updateOne() 方法。 让我们也使用 currentDate() 方法来设置钢琴课事件的 dateTime 字段:

Document document = new Document().append("title", "Piano lessons");

Bson update = Updates.currentDate("dateTime");
UpdateOptions options = new UpdateOptions().upsert(false);

UpdateResult result = collection.updateOne(document, update, options);

请注意,updateOne() 的第一个参数是一个 Document 对象,MongoDB 将使用它来匹配我们数据库中的单个条目。 如果多个文档匹配,MongoDB 将只更新它遇到的第一个文档。 我们还要注意我们将 false 传递给 upsert() 方法。 如果我们改为传入 true,如果现有文档都不匹配,MongoDB 将插入一个新文档。

我们可以通过检查修改了多少文档来确认操作是否成功:

assertEquals(1, result.getModifiedCount());

5.2. 更新符合日期条件的文档

为了更新多个文档,MongoDB 提供了 updateMany 方法。 在此示例中,我们将更新与查询中的日期范围匹配的多个events 。

updateOne() 不同,updateMany() 方法需要第二个 Bson 对象来封装查询条件,该条件将定义我们要更新的文档。 在这种情况下,我们将通过引入 lt 字段运算符来指定涵盖 2022 年所有事件的日期范围:

LocalDate updateManyFrom = LocalDate.of(2022, 1, 1);
LocalDate updateManyTo = LocalDate.of(2023, 1, 1);

Bson query = Filters.and(Filters.gte("dateTime", updateManyFrom), Filters.lt("dateTime", updateManyTo));
Bson updates = Updates.currentDate("dateTime");

UpdateResult result = collection.updateMany(query, updates);

就像 updateOne() 一样,我们可以通过检查 result 对象的更新计数来确认此操作更新了多个events:

assertEquals(2, result.getModifiedCount());

6. 删除符合日期条件的文档

与更新一样,我们可以一次从数据库中删除一个或多个文档。 假设我们需要删除 2022 年的所有event。让我们使用 Bson 日期范围查询和 deleteMany() 方法来做到这一点:

LocalDate deleteFrom = LocalDate.of(2022, 1, 1);
LocalDate deleteTo = LocalDate.of(2023, 1, 1);

Bson query = Filters.and(Filters.gte("dateTime", deleteFrom), Filters.lt("dateTime", deleteTo));
DeleteResult result = collection.deleteMany(query);

由于我们在本教程中创建的所有事件都有一个 2022 dateTime 字段值,deleteMany() 将它们全部从我们的集合中删除。 我们可以通过检查删除计数来确认这一点:

assertEquals(2, result.getDeletedCount());

7. 使用 时区(Time Zones)

MongoDB 以 UTC 存储日期,并且无法更改。 因此,如果我们希望我们的日期字段特定于一个时区,我们可以将时区偏移存储在一个单独的字段中并自己进行转换。 让我们将该字段添加为 String

public String timeZoneOffset;

我们需要调整构造函数,以便在创建events时设置新字段:

public Event(String title, String location, LocalDateTime dateTime, String timeZoneOffset) {
    this.title = title;
    this.location = location;
    this.dateTime = dateTime;
    this.timeZoneOffset = timeZoneOffset;
}

我们现在可以创建特定时区的events并将其插入到我们的数据库中。 让我们使用 ZoneOffset 类来避免手动格式化时区偏移 String

LocalDateTime utcDateTime = LocalDateTime.of(2022, 6, 20, 11, 0, 0);

Event pianoLessonsTZ = new Event("Piano lessons", "Baz Bvld", utcDateTime, ZoneOffset.ofHours(2).toString());
InsertOneResult pianoLessonsTZInsertResult = collection.insertOne(pianoLessonsTZ);

assertNotNull(pianoLessonsTZInsertResult.getInsertedId());

请注意,由于偏移量是相对于 UTC 的,所以 dateTime 成员变量必须表示 UTC 时间,以便我们以后可以正确转换它。 从集合中检索文档后,我们可以使用偏移字段和 OffsetDateTime 类进行转换:

OffsetDateTime dateTimeWithOffset = OffsetDateTime.of(pianoLessonsTZ.dateTime, ZoneOffset.of(pianoLessonsTZ.timeZoneOffset));

8. 结尾

在本文中,我们学习了如何使用 Java 和 MongoDB 数据库执行与日期相关的 CRUD 操作。

我们使用日期值来创建、检索、更新或删除数据库中的文档。 在我们的示例中,我们介绍了各种帮助程序类并介绍了在处理日期时很有帮助的 MongoDB 运算符。 最后,为了解决 MongoDB 如何仅以 UTC 存储日期的问题,我们学习了如何处理需要特定时区的日期/时间值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱游泳的老白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值