MongoDB中使用文档ID进行查询操作概述

在这个教程中,我们将探讨如何在MongoDB中使用文档ID执行查询操作。MongoDB提供了一个*find*操作符,用于从集合中检索文档。

首先,我们将在MongoDB shell查询中查看使用文档ID查询文档的方法,然后使用Java驱动程序代码。

2. 文档ID是什么?

与任何其他数据库管理系统一样,MongoDB需要为存储在集合中的每个文档提供一个唯一的标识符,作为集合的主键。

在MongoDB中,ID由12字节组成:

  • 4字节的时间戳,表示自Unix纪元以来的秒数
  • 5字节的随机生成值,对机器和进程来说是唯一的
  • 3字节递增计数器

在MongoDB中,ID存储在一个名为\_id的字段中,并由客户端生成。因此,在将文档发送到数据库之前,应先生成ID。在客户端,我们可以使用驱动程序生成的ID或自定义生成ID。

唯一标识符存储在ObjectId类中。这个类提供了方便的方法来获取ID中存储的数据,而无需实际解析。如果插入文档时未指定\_id,MongoDB会在文档中添加\_id字段并为其分配一个唯一的ObjectId

3. 数据库初始化

首先,我们设置一个新的数据库baeldung和一个示例集合vehicle

use baeldung;
db.createCollection("vehicle");

接下来,我们使用insertMany方法向集合中添加一些文档:

db.vehicle.insertMany([
{
    "companyName":"Skoda", 
    "modelName":"Octavia",
    "launchYear":2016,
    "type":"Sports",
    "registeredNo":"SKO 1134"
},
{ 
    "companyName":"BMW",
    "modelName":"X5",
    "launchYear":2020,
    "type":"SUV",
    "registeredNo":"BMW 3325"
},
{
    "companyName":"Mercedes",
    "modelName":"Maybach",
    "launchYear":2021,
    "type":"Luxury",
    "registeredNo":"MER 9754"
}]);

成功插入后,上述命令将打印类似下面的JSON:

{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("62d01d17cdd1b7c8a5f945b9"),
        ObjectId("62d01d17cdd1b7c8a5f945ba"),
        ObjectId("62d01d17cdd1b7c8a5f945bb")
    ]
}

我们已成功设置数据库和集合。我们将使用这个数据库和集合作为所有示例的基础。

4. 使用MongoDB Shell

我们将使用db.collection.find(query, projection)方法从MongoDB查询文档。

首先,编写一个查询,返回所有vehicle集合的文档:

db.vehicle.find({});

上述查询返回所有文档:

{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945b9"), "companyName" : "Skoda",
    "modelName" : "Octavia", "launchYear" : 2016, "type" : "Sports", "registeredNo" : "SKO 1134" }
{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945ba"), "companyName" : "BMW",
    "modelName" : "X5", "launchYear" : 2020, "type" : "SUV", "registeredNo" : "BMW 3325" }
{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945bb"), "companyName" : "Mercedes",
    "modelName" : "Maybach", "launchYear" : 2021, "type" : "Luxury", "registeredNo" : "MER 9754" }

接下来,编写一个查询,使用上面结果中返回的ID获取vehicle集合的文档:

db.vehicle.find(
{
    "_id": ObjectId("62d01d17cdd1b7c8a5f945b9")
});

此查询返回\_id等于ObjectId("62d01d17cdd1b7c8a5f945b9")vehicle集合文档:

{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945b9"), "companyName" : "Skoda",
    "modelName" : "Octavia", "launchYear" : 2016, "type" : "Sports", "registeredNo" : "SKO 1134" }

此外,我们可以使用in查询运算符根据ID获取多个vehicle集合文档:

db.vehicle.find(
{
    "_id": {
        $in: [
            ObjectId("62d01d17cdd1b7c8a5f945b9"),
            ObjectId("62d01d17cdd1b7c8a5f945ba"),
            ObjectId("62d01d17cdd1b7c8a5f945bb")
        ]
    }
});

上述查询返回in运算符中查询到的所有vehicle集合文档:

{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945b9"), "companyName" : "Skoda",
    "modelName" : "Octavia", "launchYear" : 2016, "type" : "Sports", "registeredNo" : "SKO 1134" }
{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945ba"), "companyName" : "BMW",
    "modelName" : "X5", "launchYear" : 2020, "type" : "SUV", "registeredNo" : "BMW 3325" }
{ "_id" : ObjectId("62d01d17cdd1b7c8a5f945bb"), "companyName" : "Mercedes",
    "modelName" : "Maybach", "launchYear" : 2021, "type" : "Luxury", "registeredNo" : "MER 9754" }

同样,可以使用所有查询运算符作为find()方法的过滤器,使用要查询的ID。

另外,值得注意的是,在使用\_id字段查询文档时,文档ID的字符串值应指定为ObjectId(),而不是String

让我们尝试使用字符串值查询现有文档:

db.vehicle.find(
{
    "_id": "62d01d17cdd1b7c8a5f945b9"
});

不幸的是,上述查询不会返回任何文档,因为没有文档具有ID为String62d01d17cdd1b7c8a5f945b9的。

5. 使用Java驱动程序

到目前为止,我们已经了解了如何在MongoDB Shell中使用ID查询文档。现在,我们将使用MongoDB Java驱动程序实现相同的功能。

在执行更新操作之前,我们首先连接到baeldung数据库中的vehicle集合:

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

在这种情况下,我们连接到运行在本地主机默认端口27017上的MongoDB。

首先,编写代码使用ID查询文档:

Bson filter = Filters.eq("_id", new ObjectId("62d01d17cdd1b7c8a5f945b9"));
FindIterable<Document> documents = collection.find(filter);

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

在这里,我们向find()方法传递一个Bson过滤器,其中包含\_id字段以进行查询。上述代码将返回\_id等于ObjectId("62d01d17cdd1b7c8a5f945b9")vehicle集合文档。

接下来,编写代码查询具有多个ID的文档:

Bson filter = Filters.in("_id", new ObjectId("62d01d17cdd1b7c8a5f945b9"),
  new ObjectId("62d01d17cdd1b7c8a5f945ba"));
FindIterable<Document> documents = collection.find(filter);

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

上述查询返回查询到的所有vehicle集合文档。

最后,尝试使用驱动程序生成的ID查询vehicle集合:

Bson filter = Filters.eq("_id", new ObjectId());
FindIterable<Document> documents = collection.find(filter);

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

上述查询不会返回任何文档,因为集合中不存在具有新生成ID的文档。

6. 总结

在这篇文章中,我们学习了如何在MongoDB中使用文档ID查询文档。首先,我们在MongoDB shell查询中探讨了这些用例,然后讨论了相应的Java驱动程序代码。

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