MongoDB查询教程:搜索与检索文档

本教程将探讨如何在MongoDB中执行搜索操作,从集合中检索文档。MongoDB提供了find运算符来根据查询条件从集合中查询文档。find运算符的主要目的是根据查询条件选择集合中的文档,并返回指向所选文档的游标。

1. 概述

在这个教程中,我们将首先在MongoDB Shell查询中查看find运算符,然后使用Java驱动程序代码。

2. 数据库初始化

在进行find操作之前,我们需要设置一个名为baeldung的数据库和一个示例集合employee

db.employee.insertMany([
{
    "employeeId":"EMP1",
    "name":"Sam", 
    "age":23,
    "type":"Full Time",
    "department":"Engineering"
},
{ 
    "employeeId":"EMP2",
    "name":"Tony",
    "age":31,
    "type":"Full Time",
    "department":"Admin"
},
{
    "employeeId":"EMP3",
    "name":"Lisa",
    "age":42,
    "type":"Part Time",
    "department":"Engineering"
}]);

插入成功后,上述查询将返回类似下面的JSON结果:

{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("62a88223ff0a77909323a7fa"),
        ObjectId("62a88223ff0a77909323a7fb"),
        ObjectId("62a88223ff0a77909323a7fc")
    ]
}

此时,我们已在集合中插入了一些文档,用于执行各种类型的find操作。

3. 使用MongoDB Shell

从MongoDB集合中查询文档,我们使用db.collection.find(query, projection)方法。该方法接受两个可选参数——queryprojection——作为MongoDB的BSON文档。

query参数接受带有查询运算符的选择过滤器。要从MongoDB集合中检索所有文档,我们可以省略这个参数或传递一个空文档。

接下来,projection参数用于指定从匹配文档中返回的字段。要返回匹配文档中的所有字段,我们可以省略此参数。

首先,让我们从一个基本的find查询开始,它将返回集合中的所有文档:

db.employee.find({});

此查询将返回employee集合的所有文档:

{ "_id" : ObjectId("62a88223ff0a77909323a7fa"), "employeeId" : "1", "name" : "Sam", "age" : 23, "type" : "Full Time", "department" : "Engineering" }
{ "_id" : ObjectId("62a88223ff0a77909323a7fb"), "employeeId" : "2", "name" : "Tony", "age" : 31, "type" : "Full Time", "department" : "Admin" }
{ "_id" : ObjectId("62a88223ff0a77909323a7fc"), "employeeId" : "3", "name" : "Ray", "age" : 42, "type" : "Part Time", "department" : "Engineering" }

接下来,编写一个查询,返回所有属于“Engineering”部门的员工:

db.employee.find(
{
    "department":"Engineering"
});

上述查询返回所有department等于“Engineering”的employee集合文档:

{ "_id" : ObjectId("62a88223ff0a77909323a7fa"), "employeeId" : "1", "name" : "Sam", "age" : 23, "type" : "Full Time", "department" : "Engineering" }
{ "_id" : ObjectId("62a88223ff0a77909323a7fc"), "employeeId" : "3", "name" : "Ray", "age" : 42, "type" : "Part Time", "department" : "Engineering" }

最后,编写一个查询,获取所有属于“Engineering”部门的员工的nameage

db.employee.find(
{
    "department":"Engineering"
},
{
    "name":1,
    "age":1
});

此查询只返回满足查询条件的文档的nameage字段:

{ "_id" : ObjectId("62a88223ff0a77909323a7fa"), "name" : "Sam", "age" : 23 }
{ "_id" : ObjectId("62a88223ff0a77909323a7fc"), "name" : "Ray", "age" : 42 }

请注意,默认情况下,所有文档都会包含_id字段,除非明确排除。

另外,重要的是要知道find运算符返回一个指向匹配查询过滤器的文档游标。MongoDB Shell会自动迭代游标,显示最多20个文档。

此外,MongoDB Shell还提供了一个findOne()方法,它返回满足指定查询条件的单个文档。如果有多个文档匹配,将按照磁盘上文档的自然顺序返回第一个文档:

db.employee.findOne();

find()不同,上述查询将仅返回单个文档,而不是游标:

{
    "_id" : ObjectId("62a99e22a849e1472c440bbf"),
    "employeeId" : "EMP1",
    "name" : "Sam",
    "age" : 23,
    "type" : "Full Time",
    "department" : "Engineering"
}

4. 使用Java驱动

到目前为止,我们已经了解了如何在MongoDB Shell中执行find操作。接下来,我们将使用MongoDB Java驱动实现相同的操作。在开始之前,先创建一个到employee集合的MongoClient连接:

MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase database = mongoClient.getDatabase("baeldung");
MongoCollection<Document> collection = database.getCollection("employee");

这里,我们连接到运行在默认端口27017的MongoDB服务器。接下来,从连接创建的MongoDatabase实例中获取MongoCollection的实例。

首先,要在MongoCollection实例上调用find()方法来执行find操作。让我们看看如何从集合中检索所有文档:

FindIterable<Document> documents = collection.find();
MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
    System.out.println(cursor.next());
}

请注意,find()方法返回一个FindIterable<Document>实例。然后,我们通过调用FindIterable实例的iterator()方法获取一个MongoCursor实例。最后,我们遍历游标以检索每个文档。

接下来,添加查询运算符来过滤find操作返回的文档:

Bson filter = Filters.eq("department", "Engineering");
FindIterable<Document> documents = collection.find(filter);

MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
    System.out.println(cursor.next());
}

在这里,我们将一个Bson过滤器作为参数传递给find()方法。我们可以使用任何组合的查询运算符作为find()方法的过滤器。上面的片段将返回所有department为“Engineering”的文档。

再进一步,编写一个片段,只返回匹配选择条件的文档中的nameage字段:

Bson filter = Filters.eq("department", "Engineering");
Bson projection = Projections.fields(Projections.include("name", "age"));
FindIterable<Document> documents = collection.find(filter)
  .projection(projection);

MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
    System.out.println(cursor.next());
}

在这里,我们在FindIterable实例上调用projection()方法。我们传递一个Bson过滤器作为projection()方法的参数。我们可以使用投影操作包括或排除最终结果中的任何字段。有关直接使用MongoDB驱动和Bson的替代方法,请参阅我们的Spring Data MongoDB中投影的指南

最后,我们可以通过在FindIterable实例上使用first()方法来获取结果中的第一个文档。这将返回单个文档,而不是MongoCursor实例:

FindIterable<Document> documents = collection.find();
Document document = documents.first();

5. 结论

在这篇文章中,我们学习了如何在MongoDB中使用不同的方法执行find操作。我们使用查询运算符来检索匹配特定选择条件的具体文档。此外,我们还学会了如何执行投影,以确定匹配文档中返回哪些字段。

首先,我们探讨了MongoDB Shell查询中的find操作用法,然后讨论了相应的Java驱动代码。

所有这些示例和代码片段的实现可在GitHub上找到。