插入文档
Overview
在本指南中,您可以了解如何使用 PyMongo 通过执行插入操作将文档添加到 MongoDB 集合。
插入操作将一个或多个文档插入 MongoDB 集合。 您可以使用 insert_one()
或insert_many()
方法执行插入操作。
注意
_id字段必须是唯一的
在MongoDB集合中,每个文档都必须包含具有唯一值的 _id
字段。
如果为 _id
字段指定值,则必须确保该值在集合中是唯一的。如果不指定值,驾驶员会自动为该字段生成唯一的 ObjectId
值。
我们建议让驾驶员自动生成 _id
值以确保唯一性。重复的 _id
值违反了唯一索引约束,导致驾驶员返回错误。
样本数据
本指南中的示例使用 Atlas示例数据集中的sample_restaurants.restaurants
集合。 要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅 PyMongo入门教程。
插入一个文档
要将单个文档添加到 MongoDB 集合,请调用insert_one()
方法并传递要添加的文档。
以下示例将文档插入restaurants
集合:
sample_restaurants.restaurants.insert_one({"name" : "Mongo's Burgers"})
您还可以将自定义类的实例传递给 insert_one()
方法。如果您使用类型检查工具,这将提供额外的类型安全性。您传递的实例必须从 TypedDict
类继承。
注意
Python 3.7 及更早版本中的 TypedDict
TypedDict 类位于 typing
模块中,该模块仅在Python 3.8 及更高版本中可用。要在早期版本的Python中使用 TypedDict
类,请安装typing_extensions包。
以下示例将 Restaurant
类的实例传递给 insert_one()
方法,以提高类型安全性:
class Restaurant(TypedDict): name: str sample_restaurants.restaurants.insert_one(Restaurant(name="Mongo's Burgers")
插入多个文档
要将多个文档添加到 MongoDB 集合,请调用insert_many()
方法并传递要添加的文档列表。
以下示例将文档列表插入restaurants
集合:
document_list = [ { "name" : "Mongo's Burgers" }, { "name" : "Mongo's Pizza" } ] sample_restaurants.restaurants.insert_many(document_list)
您还可以将自定义类的实例列表传递给 insert_many()
方法。如果您使用类型检查工具,这将提供额外的类型安全性。您传递的实例必须继承自 TypedDict
类。
注意
Python 3.7 及更早版本中的 TypedDict
TypedDict 类位于 typing
模块中,该模块仅在Python 3.8 及更高版本中可用。要在早期版本的Python中使用 TypedDict
类,请安装typing_extensions包。
以下示例调用 insert_many()
方法并传递包含 Restaurant
类实例的列表。这增加了插入操作的类型安全性。
class Restaurant(TypedDict): name: str document_list = [ Restaurant(name="Mongo's Burgers"), Restaurant(name="Mongo's Pizza") ] sample_restaurants.restaurants.insert_many(document_list)
修改插入行为
insert_one()
方法可以选择接受其他参数,这些参数表示可用于配置插入操作的选项。 如果不指定任何其他参数,驱动程序将不会自定义插入操作。
属性 | 说明 |
---|---|
| If set to True , allows the write to opt out of
document-level validation.Defaults to False . |
| An instance of ClientSession . |
| A comment to attach to the operation. For more information, see the insert command
fields guide in the
MongoDB Server manual for more information. |
insert_many()
方法接受前面的可选参数以及可选的ordered
属性:
属性 | 说明 |
---|---|
| If set to True , the driver sends documents to the
server in the order provided. If an error occurs, the driver
and server cancel all remaining insert operations.Defaults to True . |
例子
以下代码使用insert_many()
方法将三个新文档插入到集合中。 由于第二个方法参数为bypass_document_validation = True
,因此此插入操作会绕过文档级验证。
document_list = [ { "name" : "Mongo's Burgers" }, { "name" : "Mongo's Pizza" }, { "name" : "Mongo's Tacos" } ] sample_restaurants.restaurants.insert_many(document_list, bypass_document_validation = True)
故障排除
客户端类型注解
如果没有为 MongoClient
对象添加类型注解,类型检查器可能会显示类似于以下内容的错误:
from pymongo import MongoClient client = MongoClient() # error: Need type annotation for "client"
解决方案是将 MongoClient
对象注释为 client: MongoClient
或 client: MongoClient[Dict[str, Any]]
。
不兼容类型
如果您指定 MongoClient
作为类型提示,但不包含文档、键和值的数据类型,则类型检查器可能会显示类似于以下内容的错误:
error: Dict entry 0 has incompatible type "str": "int"; expected "Mapping[str, Any]": "int"
解决方案是将以下类型提示添加到 MongoClient
对象:
``client: MongoClient[Dict[str, Any]]``
如果将列表传递给 insert_one()
方法,则可能会看到类似的错误:
error: Argument 1 to "insert_one" of "Collection" has incompatible type "List[Dict[<nothing>, <nothing>]]"; expected "Mapping[str, Any]"
发生此错误的原因是 insert_one()
方法接受文档,而不是列表。您可以通过将文档传递给 insert_one()
方法或改为调用 insert_many()
方法来解决此错误。
TypedDict 缺少_id键
如果不指定 _id
字段, PyMongo会自动将其插入到文档中。您可以在运行时检索_id
字段的值,但如果您使用 MyPy 或其他工具执行静态类型检查,它不会在您的类中找到 _id
字段,并且会显示类似于以下内容的错误:以下:
TypedDict has no key "_id"
这是由类似下面的代码造成的:
from typing import TypedDict from pymongo import MongoClient from pymongo.collection import Collection class Movie(TypedDict): name: str year: int client: MongoClient = MongoClient() collection: Collection[Movie] = client.test.test inserted = collection.insert_one(Movie(name="Jurassic Park", year=1993)) result = collection.find_one({"name": "Jurassic Park"}) # _id is present but was added by PyMongo; this will raise a type-checking error assert result["_id"]
一种解决方案是在使用 _id
字段的行末尾添加 # type:ignore
注释。此注释指示类型检查工具忽略该行导致的任何错误。以下示例展示了如何实现该解决方案;
from typing import TypedDict from pymongo import MongoClient from pymongo.collection import Collection class Movie(TypedDict): name: str year: int collection: Collection[Movie] = client.test.test inserted = collection.insert_one( Movie(name="Jurassic Park", year=1993) ) result = collection.find_one({"name": "Jurassic Park"}) assert result is not None assert result["_id"] # type:ignore[typeddict-item]
您不必忽略类型错误,只需在模型类中包含 _id
字段,并在创建类实例时显式指定此字段的值,即可避免此类错误。以下代码展示了如何实现该解决方案:
from typing import TypedDict from pymongo import MongoClient from pymongo.collection import Collection from bson import ObjectId class Movie(TypedDict): _id: ObjectId name: str year: int collection: Collection[ExplicitMovie] = client.test.test inserted = collection.insert_one( ExplicitMovie(_id=ObjectId(), name="Jurassic Park", year=1993) ) result = collection.find_one({"name": "Jurassic Park"}) assert result is not None assert result["_id"]
将 _id
字段添加到自定义类的一个缺点是,您必须为所创建的类的每个实例包含该字段的值。为避免这种情况,您可以安装 typing.NotRequired
包,其中包含 NotRequired
类型提示。如果对 _id
字段使用此类型提示,则可以在运行时访问权限_id
字段的值,而不会看到任何编译时类型错误。
以下代码示例展示了如何实现此解决方案:
from typing import TypedDict, NotRequired from pymongo import MongoClient from pymongo.collection import Collection from bson import ObjectId class Movie(TypedDict): _id: NotRequired[ObjectId] name: str year: int client: MongoClient = MongoClient() collection: Collection[Movie] = client.test.test inserted = collection.insert_one(Movie(name="Jurassic Park", year=1993)) result = collection.find_one({"name": "Jurassic Park"}) assert result is not None assert result["_id"]
重要
NotRequired 需要Python 3.11+
NotRequired 类仅在Python 3.11 及更高版本中可用。要在早期版本的Python中使用 NotRequired
,请安装typing_extensions包。
更多信息
有关使用PyMongo插入文档的可运行代码示例,请参阅增删改查操作。
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: