1、概览 {#1概览}
在使用 Spring Data MongoDB 时,可能需要比默认级别(INFO)更高的日志,以查看执行语句或查询参数等一些附加信息。
2、配置 MongoDB 查询日志 {#2配置-mongodb-查询日志}
Spring Data MongoDB 通过 MongoOperations
接口或其主要的实现 MongoTemplate
来访问数据,因此只需为 MongoTemplate
类配置调 Debug 级别的日志即可。
与其他 Spring 或 Java 应用一样,可以使用日志库并为 MongoTemplate
定义日志级别。类似于如下:
<logger name="org.springframework.data.mongodb.core.MongoTemplate" level="DEBUG" />
如果是 Spring Boot 应用,可以直接在 application.properties
文件中进行配置:
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
同样,也可以使用 YAML 文件:
logging:
level:
org:
springframework:
data:
mongodb:
core:
MongoTemplate: DEBUG
3、日志测试类 {#3日志测试类}
创建一个 Book
类:
@Document(collection = "book")
public class Book {
@MongoId
private ObjectId id;
private String bookName;
private String authorName;
// getter 和 setter 方法
}
创建一个简单的测试类用于测试,并查看输出日志。
使用嵌入式 MongoDB 进行测试,所需依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>${embed.mongo.version}</version>
<scope>test</scope>
</dependency>
最后,使用 @SpringBootTest
定义测试类:
@SpringBootTest
@TestPropertySource(properties = { "logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG" })
public class LoggingUnitTest {
private static final String CONNECTION_STRING = "mongodb://%s:%d";
private MongodExecutable mongodExecutable;
private MongoTemplate mongoTemplate;
@AfterEach
void clean() {
mongodExecutable.stop();
}
@BeforeEach
void setup() throws Exception {
String ip = "localhost";
int port = 27017;
ImmutableMongodConfig mongodbConfig = MongodConfig.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();
MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodbConfig);
mongodExecutable.start();
mongoTemplate = new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, ip, port)), "test");
}
// tests
}
4、日志示例 {#4日志示例}
本节中,定义了一些简单的测试用例,演示最常见的查找、插入、更新或聚合文档的场景。
我们可以观察这些测试输出的日志。
4.1、Insert {#41insert}
首先、插入一个文档:
Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");
mongoTemplate.insert(book);
日志会显示正在插入的 collection
。在查找文档时,id
也会被记录在日志中。
[2022-03-20 17:42:47,093]-[main] DEBUG MongoTemplate - Inserting Document containing fields: [bookName, authorName, _class] in collection: book
...
[2022-03-20 17:42:47,144]-[main] DEBUG MongoTemplate - findOne using query: { "id" : { "$oid" : "623759871ff6275fe96a5ecb"}} fields: Document{{}} for class: class com.baeldung.mongodb.models.Book in collection: book
[2022-03-20 17:42:47,149]-[main] DEBUG MongoTemplate - findOne using query: { "_id" : { "$oid" : "623759871ff6275fe96a5ecb"}} fields: {} in db.collection: test.book
4.2、Update {#42update}
同样,在更新文档时也是如此:
Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");
mongoTemplate.insert(book);
String authorNameUpdate = "AuthorNameUpdate";
book.setAuthorName(authorNameUpdate);
mongoTemplate.updateFirst(query(where("bookName").is("Book")), update("authorName", authorNameUpdate), Book.class);
可以在日志中看到实际更新的文档字段:
[2022-03-20 17:48:31,759]-[main] DEBUG MongoTemplate - Calling update using query: { "bookName" : "Book"} and update: { "$set" : { "authorName" : "AuthorNameUpdate"}} in collection: book
4.3、Batch Insert {#43batch-insert}
添加一个批量插入的示例:
Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");
Book book1 = new Book();
book1.setBookName("Book1");
book1.setAuthorName("Author1");
mongoTemplate.insert(Arrays.asList(book, book1), Book.class);
可以在日志中看到插入的文档数量:
[2022-03-20 17:52:00,564]-[main] DEBUG MongoTemplate - Inserting list of Documents containing 2 items
4.4、Remove {#44remove}
删除文档:
Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");
mongoTemplate.insert(book);
mongoTemplate.remove(book);
可以从日志中看到已删除文档的 ID:
[2022-03-20 17:56:42,151]-[main] DEBUG MongoTemplate - Remove using query: { "_id" : { "$oid" : "62375cca2a2cba4db774d8c1"}} in collection: book.
4.5、聚合(Aggregation) {#45聚合aggregation}
在这种情况下,需要定义一个结果类。
例如,根据 authorName
进行聚合:
public class GroupByAuthor {
@Id
private String authorName;
private int authCount;
// get/set 方法
}
接下来,定义一个 group
测试用例:
Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");
Book book1 = new Book();
book1.setBookName("Book1");
book1.setAuthorName("Author");
Book book2 = new Book();
book2.setBookName("Book2");
book2.setAuthorName("Author");
mongoTemplate.insert(Arrays.asList(book, book1, book2), Book.class);
GroupOperation groupByAuthor = group("authorName")
.count()
.as("authCount");
Aggregation aggregation = newAggregation(groupByAuthor);
AggregationResults<GroupByAuthor> aggregationResults = mongoTemplate.aggregate(aggregation, "book", GroupByAuthor.class);
可以从日志中看到聚合了哪个字段以及聚合管道(Aggregation Pipeline)的类型:
[2022-03-20 17:58:51,237]-[main] DEBUG MongoTemplate - Executing aggregation: [{ "$group" : { "_id" : "$authorName", "authCount" : { "$sum" : 1}}}] in collection book
5、总结 {#5总结}
本文介绍了如何为 Spring Data MongoDB 开启 Debug 级别的日志,以在执行查询、更新、删除和聚合操作时看到更加详细的日志信息。
参考:https://www.baeldung.com/spring-boot-mongodb-logging