Mongoengine 简明教程

MongoEngine - Quick Guide

MongoEngine - MongoDB

在过去十年中,NoSQL 数据库变得越来越受欢迎。在当今实时 Web 应用程序的世界中,移动设备和嵌入式设备产生了大量数据。传统的关联数据库(如 Oracle、MySQL 等)不适用于字符串。此类数据的处理过程也存在困难,因为它们具有固定和预定义的模式,且不可扩展。NoSQL 数据库拥有灵活的模式,并以分布式的方式存储在大量社区服务器上。

NoSQL databases have seen rise in popularity in the last decade. In today’s world of real time web applications, huge amount of data is being generated with mobile and embedded devices. Traditional relational databases (like Oracle, MySQL, etc.) are not suitable for strings. The processing of such data is also difficult as they have fixed and predefined schema, and are not scalable. NOSQL databases have flexible schema and are stored in distributed manner on a large number of community servers.

NoSQL 数据库根据数据的组织方式进行分类。MongoDB 是一款流行的文档存储 NoSQL 数据库。MongoDB 数据库的基本组成部分被称为文档。文档是由 JSON 格式中存储的一组键值对。在一个集合中存储了多个文档。一个集合可以看作是任何关系数据库中的一张表,而一个文档则是表中的一行。不过需要指出的是,由于 MongoDB 无模式,一个集合中每份文档中的键值对数量不一定相同。

NOSQL databases are classified on the basis of organization of data. MongoDB is a popular Document Store NOSQL database. Fundamental constituent of a MongoDB database is called a document. A document is a collection of key-value pairs stored in JSON format. More than one documents are stored in a collection. A collection can be considered as analogous to a table in any relational database, and a Document as row in a table. However, it should be noted that since MongoDB is schema less, number of key-value pairs in each document of a Collection need not be the same.

MongoDB 是由 MongoDB Inc. 开发的。它是一个通用的、基于分布式文档的数据库。它提供企业版和社区版。可在 https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2012plus-4.2.6-signed.msi 下载适用于 Windows 操作系统的最新版本社区版。

MongoDB is developed by MongoDB Inc. It is a general-purpose, distributed document based database. It is available in enterprise as well as community edition. Latest version of Community version for Windows operating system can be downloaded from https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2012plus-4.2.6-signed.msi.

在您选择的文件夹中安装 MongoDB,并使用以下命令启动服务器 −

Install MongoDB in a folder of your choice and start the server with the following command−

D:\mongodb\bin>mongod

服务器现已准备好接受端口 27017 上的传入连接请求。MongoDB 数据库存储在 bin/data 目录中。可以通过上述命令中的 –dbpath 选项更改此位置。

Server is now ready for incoming connection requests at port 27017. MongoDB databases are stored in bin/data directory. This location can be changed by –dbpath option in above command.

在另一个命令终端中,使用以下命令启动 MongoDB 控制台 −

In another command terminal, start MongoDB console with the following command −

D:\mongodb\bin>mongo

MongoDB 提示类似于我们在 MySQL 或 SQLite 终端中通常看到的提示。所有数据库操作(例如创建数据库、插入文档、更新和删除以及检索文档)都可以在控制台中完成。

MongoDB prompt is similar to what we normally see in MySQL or SQLite terminal. All database operations such as creating database, inserting a document, updating and deleting as well as retrieval of documents can be done from within the console.

E:\mongodb\bin>mongo
MongoDB shell version v4.0.6
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("0d848b11-acf7-4d30-83df-242d1d7fa693") }
MongoDB server version: 4.0.6
---
>

正在使用的默认数据库为 test。

Default database in use is test.

> db
Test

使用 'use' 命令可将任何其他数据库设置成当前数据库。如果指定的数据库不存在,则会创建新的数据库。

With 'use' command any other database is set as current. If the named database does not exist, new one is created.

> use mydb
switched to db mydb

请参阅我们在 https://www.tutorialspoint.com/mongodb/index.htm 上的关于 MongoDB 的详细教程。

Please refer to our detailed tutorial on MongoDB at https://www.tutorialspoint.com/mongodb/index.htm.

MongoEngine - MongoDB Compass

MongoDB 还开发了一款用于处理 MongoDB 数据库的 GUI 工具。它被称为 MongoDB Compass。这是一款无需手动编写查询即可执行所有 CRUD 操作的便利工具。它有助于执行诸多活动,如索引编制、文档验证等。

MongoDB has also developed a GUI tool for handling MongoDB databases. It is called MongoDB Compass. It is a convenient tool for performing all CRUD operations without manually writing queries. It helps in many activities such as indexing, document validation, etc.

可从 https://www.mongodb.com/download-center/compass 下载 MongoDB Compass 的社区版,并启动 MongoDBCompassCommunity.exe (确保在启动 Compass 之前 MongoDB 服务器正在运行)。通过提供正确的 host 和 port 号连接到本地服务器。

Download community edition of MongoDB Compass from https://www.mongodb.com/download-center/compass and start MongoDBCompassCommunity.exe (Ensure that MongoDB server is running before starting Compass). Connect to the local server by giving correct host and port number.

databases

如下列出目前可用的所有数据库 −

All the databases currently available will be listed as below −

new database

单击 + 按钮(在左面板底部显示)可创建新数据库。

Click on + button (shown at the bottom of left panel) to create new database.

name of database

从列表中选择数据库的名称,并选择一个集合,如下所示 −

Choose name of database from list and select a Collection as shown below −

csv or json file

您可以直接添加文档,或者从 CSV 或 JSON 文件中导入。

You can add document directly or import from CSV or JSON file.

insert document

从添加数据下拉菜单中选择插入文档。

Choose Insert Document from Add data drop down.

documents added

添加的文档将以 JSON、列表或表格形式显示 −

Documents added will be displayed in JSON, list or tabular form −

relational database

请注意,正如关系数据库中的表具有主键一样,MongoDB 数据库中的文档具有一个自动生成的特殊键称为“ _id ”。

Note that, just as a table in relational database has a primary key, document in MongoDB database has a special key called "_id" that is automatically generated.

MongoDB Inc. 为连接到 MongoDB 数据库提供了一个 Python 驱动程序。它称为 PyMongo ,其用法类似于标准 SQL 查询。

MongoDB Inc. provides a Python driver for connection with MongoDB databases. It is called PyMongo whose usage is similar to standard SQL queries.

安装 PyMongo 模块后,我们需要 MongoClient 类的对象才能与 MongoDB 服务器交互。

After installing PyMongo module, we need object of MongoClient class for interacting with MongoDB server.

<<< from pymongo import MongoClient
<<< client=MongoClient()

使用以下语句创建新数据库 −

New database is created with the following statement −

db=client.mydatabase

对该数据库上的 CRUD 操作使用 insert_one()(或 insert_many())、find()、update() 和 delete() 方法进行。PyMongo 库的详细讨论可 https://www.tutorialspoint.com/python_data_access/python_mongodb_introduction.htm 获得。

CRUD operations on this database are performed with methods such as insert_one() (or insert_many()), find(), update() and delete() methods. Detailed discussion of PyMongo library is available at https://www.tutorialspoint.com/python_data_access/python_mongodb_introduction.htm.

但是,除非将 Python 的用户定义对象转换为 MongoDB 的数据类型,否则它不能存储在数据库中。这就是我们需要 MongoEngine 库的地方。

However, Python’s user defined objects cannot be stored in database unless it is converted in MongoDB’s data types. This is where we need MongoEngine library.

MongoEngine - Object Document Mapper

MongoDB 是基于文档的数据库。每个文档都是字段和值的 JSON 类似表示。MongoDB 中的文档大致等效于 RDBMS 表中的行(MongoDB 等效的表是集合)。尽管 MongoDB 不强制使用任何预定义架构,但文档中的字段对象具有一定数据类型。MongoDB 数据类型与 Python 的主数据类型非常相似。如果必须存储 Python 的用户定义类的对象,则必须手动将其属性解析为等效的 MongoDB 数据类型。

MongoDB is a document based database. Each document is a JSON like representation of fields and values. A document in MongoDB is roughly equivalent to a row in RDBMS table (MongoDB equivalent of table is Collection). Even though MongoDB does not enforce any predefined schema, the field objects in a document have certain data type. MongoDB data types are very much similar to Python’s primary data types. If one has to store object of Python’s user defined class, its attributes have to be manually parsed to equivalent MongoDB data types.

MongoEngine 在 PyMongo 上提供了一个便捷的抽象层,并将 Document 类的每个对象映射到 MongoDB 数据库中的一个文档。MongoEngine API 是由 Hary Marr 在 2013 年 8 月制定的。MongoEngine 的最新版本是 0.19.1。

MongoEngine provides a convenient abstraction layer over PyMongo and maps each object of Document class to a document in MongoDB database. MongoEngine API has been developed by Hary Marr in August 2013. Latest version of MongoEngine is 0.19.1.

MongoEngine 之于 MongoDB,正如 SQLAlchemy 之于 RDBMS 数据库。MongoEngine 库提供了一个 Document 类,该类用作定义自定义类的基础。该类的属性形成 MongoDB 文档的字段。Document 类定义执行 CRUD 操作的方法。在后续主题中,我们将学习如何使用它们。

MongoEngine is to MongoDB what SQLAlchemy is to RDBMS databases. MongoEngine library provides a Document class that is used as base for defining custom class. Attributes of this class form the fields of MongoDB document. The Document class defines methods to perform CRUD operations. In subsequent topics, we shall learn how to use them.

MongoEngine - Installation

要使用 MongoEngine,您需要已安装 MongoDB,并且 MongoDB 服务器应按前面所述运行。

To use MongoEngine, you need to have already installed MongoDB and MongoDB server should be running as described earlier.

安装 MongoEngine 的最简单方法是使用 PIP 安装程序。

Easiest way to install MongoEngine is by using PIP installer.

pip install mongoengine

如果您的 Python 安装未安装 Setuptools,则必须从 https://github.com/MongoEngine/mongoengine 下载 MongoEngine 并运行以下命令 −

If your Python installation does not have Setuptools installed, you will have to download MongoEngine from https://github.com/MongoEngine/mongoengine and run the following command −

python setup.py install

MongoEngine 具有以下依赖项 −

MongoEngine has the following dependencies −

  1. pymongo>=3.4

  2. six>=1.10.0

  3. dateutil>=2.1.0

  4. pillow>=2.0.0

为了验证正确的安装,请运行 import 命令并检查版本,如下所示 −

To verify the correct installation, run import command and check version as follows −

>>> import mongoengine
>>> mongoengine.__version__
'0.19.1'

Connecting to MongoDB Database

如前所述,你应当首先使用 mongod 命令启动 MongoDB 服务器。

As mentioned earlier, you should first start MongoDB server using mongod command.

MongoEngine 提供 connect() 函数以连接到 mongodb 服务器的正在运行的实例。

MongoEngine provides connect() function to connect to a running instance of mongodb server.

from mongoengine import connect
connect(‘mydata.db’)

默认情况下,MongoDB 服务器在 localhost 上和 27017 端口上运行。若要自定义,你应当向 connect() 提供 host 和 port 参数 −

By default, MongoDB server is running on localhost and on port 27017. To customize, you should provide the host and port arguments to connect() −

connect('mydata.db', host='192.168.1.1', port=12345)

如果数据库需要身份验证,则应当提供其凭据,例如 username、password 和 authentication_source 参数。

In case the database requires authentication, its credentials such as username, password and authentication_source arguments should be provided.

connect('mydata.db', username='user1', password='***', authentication_source='admin')

MongoEngine 还支持 URI 样式的连接,而不是 IP 地址。

MongoEngine also supports URI style connections instead of IP address.

connect('mydata.db', host='mongodb://localhost/database_name')

connect() 函数有另一个可选的参数,称为 replicaset。MongoDB 是分布式数据库。存储在某一台服务器中的数据通常在许多服务器实例中复制,以确保高可用性。MongoDB 中的 replica set(副本集)是在其上维护相同数据集的 mongod 进程组。Replica set 是所有生产部署的基础。

The connect() function has another optional parameter called replicaset. MongoDB is a distributed database. Data stored in one server is usually replicated in many server instances in order to ensure high availability. A replica set in MongoDB is a group of mongod processes on which the same data set is maintained. Replica sets are the basis for all production deployments.

connect(host='mongodb://localhost/dbname?replicaSet=rs-name')

定义了以下副本集方法:

Following replica set methods are defined as follows:

rs.add()

Adds a member to a replica set.

rs.conf()

Returns the replica set configuration document.

rs.freeze()

Prevents the current member from seeking election as primary for a period of time.

rs.initiate()

Initializes a new replica set.

rs.reconfig()

Re-configures a replica set by applying a new replica set configuration object.

rs.remove()

Removes a member from a replica set.

MongoEngine 还允许连接多个数据库。你需为每个数据库提供唯一的别名。例如,以下代码将 Python 脚本连接到两个 MongoDB 数据库。

MongoEngine also allows connection with multiple databases. You need to provide unique alias name for each database. For example, following code connects Python script to two MongoDB databases.

connect(alias='db1', db='db1.db')
connect(alias='db2', db='db2.db')

MongoEngine - Document Class

MongoEngine 被称为 ODM(@(s0))。MongoEngine 定义了 Document 类。这是一个基类,其继承的类用于定义存储在 MongoDB 数据库中的一系列文档的结构和属性。此子类的每个对象形成数据库中 Collection 中的 Document。

MongoEngine is termed as ODM (Object Document Mapper). MongoEngine defines a Document class. This is a base class whose inherited class is used to define structure and properties of collection of documents stored in MongoDB database. Each object of this subclass forms Document in Collection in database.

此 Document 子类中的属性是由各种 Field 类的对象组成的。以下是一个典型的 Document 类的示例 −

Attributes in this Document subclass are objects of various Field classes. Following is an example of a typical Document class −

from mongoengine import *
class Student(Document):
   studentid = StringField(required=True)
   name = StringField(max_length=50)
   age = IntField()
   def _init__(self, id, name, age):
      self.studentid=id,
      self.name=name
      self.age=age

这类似于 SQLAlchemy ORM 中的模型类。默认情况下,数据库中 Collection 的名称是 Python 类名,采用小写字母。然而,可在 Document 类的 meta 属性中指定不同的集合名称。

This appears similar to a model class in SQLAlchemy ORM. By default, name of Collection in database is the name of Python class with its name converted to lowercase. However, a different name of collection can be specified in meta attribute of Document class.

meta={collection': 'student_collection'}

现在,声明此类的对象并调用 save() 方法以将文档存储在数据库中。

Now declare object of this class and call save() method to store the document in a database.

s1=Student('A001', 'Tara', 20)
s1.save()

MongoEngine - Dynamic Schema

MongoDB 数据库的优点之一是支持动态架构。若要创建支持动态架构的类,可从 DynamicDocument 基类进行子类化。以下是具有动态架构的 Student 类−

One of the advantages of MongoDB database is that it supports dynamic schema. To create a class that supports dynamic schema, subclass it from DynamicDocument base class. Following is the Student class with dynamic schema −

>>> class student(DynamicDocument):
... name=StringField()

第一步是要先添加 Document 。

The first step is to add first Document as before.

>>> s1=student()
>>> s1.name="Tara"
>>> connect('mydb')
>>> s1.save()

现在另一个属性添加到第二个文档中并保存。

Now add another attribute to second document and save.

>>> s2=student()
>>> setattr(s2,'age',20)
>>> s2.name='Lara'
>>> s2.save()

在数据库中,学生集合将显示两个具有动态架构的文档。

In the database, student collection will show two documents with dynamic schema.

dynamic schema

文档类的元字典可以通过指定 max_documents 和 max_size 使用限幅集合。

The meta dictionary of document class can use a Capped Collection by specifying max_documents and max_size.

max_documents − 集合中允许存储的最大文档数。

max_documents − The maximum number of documents that is allowed to be stored in the collection.

max_size − 集合的最大大小(以字节为单位)。max_size 由 MongoDB 在内部以及 mongoengine 在之前舍入为 256 的下一个倍数。

max_size − The maximum size of the collection in bytes. max_size is rounded up to the next multiple of 256 by MongoDB internally and mongoengine before.

如果没有指定 max_size 但指定了 max_documents ,则 max_size 的默认值为 10485760 字节(10MB)。

If max_size is not specified and max_documents is, max_size defaults to 10485760 bytes (10MB).

文档类的其他参数如下所列 −

Other parameters of Document class are listed below −

objects

A QuerySet object that is created lazily on access.

cascade_save()

Recursively save any references and generic references on the document.

clean()

Hook for doing document level data cleaning before validation is run.

create_index()

Creates the given indexes if required.

drop_collection()

Drops the entire collection associated with this Document type from the database.

from_json()

Converts json data to a Document instance.

modify()

Perform an atomic update of the document in the database and reload the document object using updated version.

pk

Get the primary key.

save()

Save the Document to the database. If the document already exists, it will be updated, otherwise it will be created. Returns the saved object instance.

delete()

Delete current document from database.

insert()

Performs bulk insert operation.

MongoEngine - Fields

一个 MongoEngine 文档类具有一个或多个属性。每个属性都是 Field 类的对象。BaseField 是所有字段类型的基类。BaseField 类构造函数具有以下参数−

A MongoEngine document class has one or more attributes. Each attribute is an object of Field class. BaseField is the base class or all field types. The BaseField class constructor has the following arguments −

BaseField(db_field, required, default, unique, primary_key)

db_field 表示数据库字段的名称。

The db_field represents name of database field.

required 参数决定该字段的值是否必需,默认为 false。

The required parameter decides whether value for this field is required, default is false.

default 参数包含该字段的默认值

The default parameter contains default value of this field

unique 参数默认值为 false。如果要使该字段对每个文档具有唯一值,则将其设置为 true。

The unique parameter is false by default. Set to true if you want this field to have unique value for each document.

primary_key 参数默认为 false。True 使该字段成为主键。

The primary_key parameter defaults to false. True makes this field primary key.

从 BaseField 派生了许多 Field 类。

There are a number of Field classes derived from BaseField.

Numeric Fields

IntField (32 位整数)、 LongField (64 位整数)、FloatField(浮点数)字段构造函数具有 min_value 和 max_value 参数。

IntField (32bit integer), LongField (64 bit integer), FloatField (floating point number) field constructors have min_value and max_value parameters.

还有 DecimalField 类。该字段对象的 value 是一个可以指定其精度的小数。为 DecimalField 类定义了以下参数:

There is also DecimalField class. Value of this field’s object is a float whose precision can be specified. Following arguments are defined for DecimalField class −

DecimalField(min_value, max_value, force_string, precision, rounding)

min_value

specifies minimum acceptable value

max_value

specifies maximum value the field can have

force_string

If True, value of this field is stored as a string

precision

limits the floating representation to number of digits

rounding

Number is rounded as per following predefined constants decimal.ROUND_CEILING (towards Infinity) decimal.ROUND_DOWN (towards zero) decimal.ROUND_FLOOR (towards -Infinity) decimal.ROUND_HALF_DOWN (to nearest with ties going towards zero) decimal.ROUND_HALF_EVEN (to nearest with ties going to nearest even integer) decimal.ROUND_HALF_UP (to nearest with ties going away from zero) decimal.ROUND_UP (away from zero) decimal.ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

Text Fields

StringField 对象可以存储任何 Unicode 值。可以在构造函数中指定字符串的 min_length 和 max_length。 URLField 对象是 StringField,能够将输入验证为 URL。 EmailField 将字符串验证为有效的电子邮件表示形式。

StringField object can store any Unicode value. You can specify min_length and max_length of the string in the constructor. URLField object is a StringField with capability to validate input as a URL. EmailField validates the string as a valid email representation.

StringField(max-length, min_length)
URLField(url_regex)
EmailField(domain_whiltelist, allow_utf8_user, allow_ip_domain)

domain_whitelist 参数包含您不支持的无效域列表。如果设置为 True,allow_utf8_user 参数允许字符串包含 UTF8 字符作为电子邮件的一部分。allow_ip_domain 参数默认为 false,但如果为 true,则它可以是有效的 IPV4 或 IPV6 地址。

The domain_whitelist argument contains list of invalid domains which you would not support. If set to True, allow_utf8_user parameter allows the string to contain UTF8 characters as a part of email. The allow_ip_domain parameter is false by default, but if true, it can be a valid IPV4 or IPV6 address.

以下示例使用数字和字符串字段:

Following example uses numeric and string fields −

from mongoengine import *
connect('studentDB')
class Student(Document):
   studentid = StringField(required=True)
   name = StringField()
   age=IntField(min_value=6, max-value=20)
   percent=DecimalField(precision=2)
   email=EmailField()
s1=Student()
s1.studentid='001'
s1.name='Mohan Lal'
s1.age=20
s1.percent=75
s1.email='mohanlal@gmail.com'
s1.save()

当执行上述代码时,student 集合将显示如下所示的文档:

When above code is executed, the student collection shows a document as below −

document

ListField

这种类型的字段会包装任何标准字段,从而允许将多个对象用作数据库中的列表对象。该字段可以与 ReferenceField 一起使用来实现一对多关系。

This type of field wraps any standard field, thus allowing multiple objects to be used as a list object in a database. This field can be used with ReferenceField to implement one to many relationships.

来自上述示例的学生文档类被修改为如下所示:

The student document class from above example is modified as below −

from mongoengine import *
connect('studentDB')
class Student(Document):
   studentid = StringField(required=True)
   name = StringField(max_length=50)
   subjects = ListField(StringField())
s1=Student()
s1.studentid='A001'
s1.name='Mohan Lal'
s1.subjects=['phy', 'che', 'maths']
s1.save()

添加的文档以 JSON 格式显示,如下所示:

The document added is shown in JSON format as follows −

{
"_id":{"$oid":"5ea6a1f4d8d48409f9640319"},
"studentid":"A001",
"name":"Mohan Lal",
"subjects":["phy","che","maths"]
}

DictField

DictField 类的一个对象存储一个 Python 字典对象。在相应的数据库字段里,它也将被存储。

An object of DictField class stores a Python dictionary object. In the corresponding database field as well, this will be stored.

在上述范例中,将 ListField 类型改为 DictField 类型。

In place of ListField in the above example, we change its type to DictField.

from mongoengine import *
connect('studentDB')
class Student(Document):
   studentid = StringField(required=True)
   name = StringField(max_length=50)
   subjects = DictField()
s1=Student()
s1.studentid='A001'
s1.name='Mohan Lal'
s1.subjects['phy']=60
s1.subjects['che']=70
s1.subjects['maths']=80
s1.save()

数据库中的文档表现如下−

Document in the database appears as follows −

{
"_id":{"$oid":"5ea6cfbe1788374c81ccaacb"},
"studentid":"A001",
"name":"Mohan Lal",
"subjects":{"phy":{"$numberInt":"60"},
            "che":{"$numberInt":"70"},
            "maths":{"$numberInt":"80"}
            }
}

ReferenceField

MongoDB 文档可以使用这种类型的字段存储对另一个文档的引用。借此,我们可以实现与 RDBMS 中的联接。ReferenceField 构造函数使用其他文档类的名称作为参数。

A MongoDB document can store reference to another document using this type of field. This way, we can implement join as in RDBMS. A ReferenceField constructor uses name of other document class as parameter.

class doc1(Document):
   field1=StringField()
class doc2(Document):
   field1=StringField()
   field2=ReferenceField(doc1)

在下面的范例中,StudentDB 数据库包含两个文档类,即 student 和 teacher。Student 类的文档包含对 teacher 类的对象的引用。

In following example, StudentDB database contains two document classes, student and teacher. Document of Student class contains reference to an object of teacher class.

from mongoengine import *
connect('studentDB')
class Teacher (Document):
   tid=StringField(required=True)
   name=StringField()
class Student(Document):
   sid = StringField(required=True)
   name = StringField()
   tid=ReferenceField(Teacher)

t1=Teacher()
t1.tid='T1'
t1.name='Murthy'
t1.save()

s1=Student()
s1.sid='S1'
s1.name='Mohan'
s1.tid=t1
s1.save()

运行上述代码,并在 Compass GUI 中确认结果。StudentDB 数据库中创建了两个与两个文档类相对应的集合。

Run above code and verify result in Compass GUI. Two collections corresponding to two document classes are created in StudentDB database.

添加的 teacher 文档如下:

The teacher document added is as follows −

{
"_id":{"$oid":"5ead627463976ea5159f3081"},
"tid":"T1",
"name":"Murthy"
}

student 文档的内容显示如下:

The student document shows the contents as below −

{
"_id":{"$oid":"5ead627463976ea5159f3082"},
"sid":"S1",
"name":"Mohan",
"tid":{"$oid":"5ead627463976ea5159f3081"}
}

请注意,Student 文档中的 ReferenceField 存储了相应 Teacher 文档的 _id。访问时,Student 对象会自动转换为一个引用,并且在访问相应的 Teacher 对象时取消引用。

Note that ReferenceField in Student document stores _id of corresponding Teacher document. When accessed, Student object is automatically turned into a reference, and dereferenced when corresponding Teacher object is accessed.

如需向正在定义的文档添加引用,请使用 'self' 而不是其他文档类作为引用字段的参数。请注意,使用引用字段在获取文档方面可能会导致性能不佳。

To add reference to document being defined, use ‘self’ instead of other document class as argument to ReferenceField. It may be noted that use of ReferenceField may cause poor performance as far retrieval of documents is concerned.

ReferenceField 构造函数还具有一个可选参数 reverse_delete_rule。它的值决定了在引用的文档被删除时要执行的操作。

The ReferenceField constructor also has one optional argument as reverse_delete_rule. Its value determines what to be done if the referred document is deleted.

可能的值如下:

The possible values are as follows −

  1. DO_NOTHING (0) - don’t do anything (default).

  2. NULLIFY (1) - Updates the reference to null.

  3. CASCADE (2) - Deletes the documents associated with the reference.

  4. DENY (3) - Prevent the deletion of the reference object.

  5. PULL (4) - Pull the reference from a ListField of references

可以使用引用列表来实现一对多的关系。假设一个 student 文档不得不与一个或多个 teacher 文档关联,那么 Student 类必须具有 ReferenceField 实例的 ListField。

You can implement one to many relationship using list of references. Assuming that a student document has to be related with one or more teacher documents, the Student class must have a ListField of ReferenceField instances.

from mongoengine import *
connect('studentDB')
class Teacher (Document):
tid=StringField(required=True)
name=StringField()
class Student(Document):
   sid = StringField(required=True)
   name = StringField()
   tid=ListField(ReferenceField(Teacher))
t1=Teacher()
t1.tid='T1'
t1.name='Murthy'
t1.save()
t2=Teacher()
t2.tid='T2'
t2.name='Saxena'
t2.save()
s1=Student()
s1.sid='S1'
s1.name='Mohan'
s1.tid=[t1,t2]
s1.save()

在 Compass 中确认上述代码的结果时,您会发现 student 文档具有两个 teacher 文档的引用:

On verifying result of the above code in Compass, you will find the student document having reference of two teacher documents −

Teacher Collection
{
"_id":{"$oid":"5eaebcb61ae527e0db6d15e4"},
"tid":"T1","name":"Murthy"
}
{
"_id":{"$oid":"5eaebcb61ae527e0db6d15e5"},
"tid":"T2","name":"Saxena"
}
Student collection
{
"_id":{"$oid":"5eaebcb61ae527e0db6d15e6"},
"sid":"S1","name":"Mohan",
"tid":[{"$oid":"5eaebcb61ae527e0db6d15e4"},{"$oid":"5eaebcb61ae527e0db6d15e5"}]
}

DateTimeField

DateTimeField 类的实例允许在 MongoDB 数据库中以日期格式数据。MongoEngine 查找 Python-DateUtil 库以用适当的日期格式解析数据。如果在当前安装中没有找到它,则日期使用内置的 time 模块的 time.strptime() 功能表示。这种类型的字段的默认值是当前日期时间实例。

An instance of DateTimeField class allows data in date format in MongoDB database. MongoEngine looks for Python-DateUtil library for parsing data in appropriate date format. If it is not available in current installation, date is represented using built-in time module’s time.strptime() function. Default value of field of this type is current datetime instance.

DynamicField

此字段可处理不同类型的各种数据。此类型的字段由 DynamicDocument 类内部使用。

Different and varying type of data can be handled by this field. This type of field is internally used by DynamicDocument class.

ImageField

此类型的字段对应于文档中的字段,该字段可存储图像文件。此类的构造函数可以接受 size 和 thumbnail_size 参数(二者均以像素大小计)。

This type of field corresponds to field in document that can store an image file. Constructor of this class can accept size and thumbnail_size parameters (both in terms of pixel size).

MongoEngine - Add/Delete Document

我们已使用 Document 类的 save() 方法在集合中添加了一个文档。还可以使用以下参数进一步自定义 save() 方法:

We have already used save() method of Document class to add a document in the collection. The save() method can be further customized with the help of following arguments −

force_insert

Default is False, if set to True doesn’t allow updates of existing documents.

validate

validates the document; set to False to skip.

clean

call the document clean method, validate argument should be True.

write_concern

will be used as options for the resultant getLastError command. For example, save(…​, write_concern={w: 2, fsync: True}, …​) will wait until at least two servers have recorded the write and will force an fsync on the primary server.

cascade

Sets the flag for cascading saves. You can set a default by setting “cascade” in the document meta.

cascade_kwargs

optional keyword arguments to be passed throw to cascading saves. Equivalent to cascade=True.

_refs

A list of processed references used in cascading saves

save_condition

only perform save if matching record in db satisfies condition(s). Raises OperationError if the conditions are not satisfied

signal_kwargs

kwargs dictionary to be passed to the signal calls.

在调用保存之前,您可以设置用于文档验证的清理规则。通过提供自定义 clean() 方法,您可以执行任何预验证/数据清理。

You can set cleaning rules for validation of documents before calling save(). By providing a custom clean() method, you can do any pre validation/data cleaning.

class MyDocument(Document):
   ...
   ...

   def clean(self):
      if <condition>==True:
         msg = 'error message.'
         raise ValidationError(msg)

请注意,只有在启用验证时才会调用 Cleaning,并且在调用 save() 时也会调用。

Note that Cleaning is only called if validation is turned on and when calling save().

Document 类还具有 insert() 方法来执行批量插入。它具有以下参数:

Document class also has insert() method to perform bulk insert. It has following parameters −

doc_or_docs

A document or list of documents to be inserted

load_bulk

If True, returns the list of document instances

write_concern

Extra keyword arguments are passed down to insert() which will be used as options for the resultant getLastError command.

signal_kwargs

(optional) kwargs dictionary to be passed to the signal calls

如果文档包含任何 ReferenceField 对象,则默认情况下 save() 方法不会保存对这些对象的任何更改。如果您希望保存所有引用,而不会注意到每个 save 都是一个单独的查询,那么将 cascade 作为 True 传递给 save 方法将级联任何保存。

If document contains any ReferenceField objects, then by default the save() method will not save any changes to those objects. If you want all references to be saved also, noting each save is a separate query, then passing cascade as True to the save method will cascade any saves.

通过调用 delete() 方法从集合中删除文档非常容易。请记住,只有在之前已保存文档时此操作才会生效。delete() 方法具有以下参数:

Deleting a document from its collection is very easy, by calling delete() method. Remember that it will only take effect if the document has been previously saved. The delete() method has following arguments −

signal_kwargs

(optional) kwargs dictionary to be passed to the signal calls.

write_concern

Extra keyword arguments are passed down which will be used as options for the resultant getLastError command.

要从数据库中删除整个集合,请使用 drop_collecction() 方法。它从数据库中删除与此 Document 类型关联的整个集合。如果未设置文档集合(例如,如果它是抽象的),则该方法会引发 OperationError。

To delete entire collection from database use drop_collecction() method. It drops the entire collection associated with this Document type from the database. The method raises OperationError if the document has no collection set (i.g. if it is abstract).

文档类中的 modify() 方法在数据库中执行文档的原子更新并重新加载其更新版本。如果文档已更新,则返回 True;如果数据库中的文档与查询不匹配,则返回 False。请注意,如果该方法返回 True,则对该文档所做的所有尚未保存的更改将被拒绝。

The modify() method in document class performs atomic update of the document in the database and reloads its updated version. It returns True if the document has been updated or False if the document in the database does not match the query. Note that all unsaved changes that have been made to the document are rejected if the method returns True.

Parameters

query

The update will be performed only if the document in the database matches the query

update

Django-style update keyword arguments

MongoEngine - Querying Database

connect() 函数返回 MongoClient 对象。使用此对象提供的 list_database_names() 方法,我们可以检索服务器上的数据库数。

The connect() function returns a MongoClient object. Using list_database_names() method available to this object, we can retrieve number of databases on the server.

from mongoengine import *
con=connect('newdb')
dbs=con.list_database_names()
for db in dbs:
print (db)

还可以使用 list_collection_names() 方法获取数据库中的集合列表。

It is also possible to obtain list of collections in a database, using list_collection_names() method.

collections=con['newdb'].list_collection_names()
for collection in collections:
   print (collection)

如前所述,Document 类具有 objects 属性,该属性允许访问与数据库相关的对象。

As mentioned earlier, the Document class has objects attribute that enable access to objects associated with the database.

newdb 数据库有一个与下面的 Document 类相对应的 products 集合。若要获取所有文档,我们按如下所示使用 objects 属性:

The newdb database has a products collection corresponding to Document class below. To get all documents, we use objects attribute as follows −

from mongoengine import *
con=connect('newdb')
class products (Document):
ProductID=IntField(required=True)
Name=StringField()
price=IntField()
for product in products.objects:
print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

Output

ID: 1 Name: Laptop Price: 25000
ID: 2 Name: TV Price: 50000
ID: 3 Name: Router Price: 2000
ID: 4 Name: Scanner Price: 5000
ID: 5 Name: Printer Price: 12500

MongoEngine - Filters

objects 属性是一个 QuerySet 管理器。访问时,它会创建并返回一个 QuerySet。借助于字段名称作为关键字参数,可以对查询进行过滤。例如,从上面的 products 集合中,若要打印产品名为“TV”的文档的详细信息,我们使用 Name 作为关键字参数。

The objects attribute is a QuerySet manager. It creates and returns a QuerySet when accessed. A query can be subjected to filter with the help of field names as keyword arguments. For example, from above products collection, to print details of document with name of product as ‘TV’, we use Name as keyword argument.

for product in products.objects(Name='TV'):
print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

可以将 QuerySet 对象的 filter 方法用于将过滤器应用于查询。以下代码片段也返回了名为“TV”的产品详细信息。

You can use filter method of QuerySet object to apply filter to query. Following code snippet also returns product details with name=’TV’.

qset=products.objects
for product in qset.filter(Name='TV'):
   print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

MongoEngine - Query Operators

除了使用 = 操作符检查是否相等外,MongoEngine 中还定义了以下逻辑操作符。

In addition to = operator to check equality, the following logical operators are defined in MongoEngine.

ne

not equal to

lt

less than

lte

less than or equal to

gt

greater than

gte

greater than or equal to

not

negate a standard check, may be used before other operators

in

value is in list

nin

value is not in list

mod

value % x == y, where x and y are two provided values

all

every item in list of values provided is in array

size

the size of the array is

exists

value for field exists

这些运算符必须附加到带有双下划线 __ 的字段名。

These operators must be attached to field name with double underscore __.

要使用大于运算符 (gt),使用以下格式 -

To use greater than (gt) operator, use the following format −

#using greater than operator
for product in products.objects(price__gt=10000):
   print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

Output

ID: 1 Name: Laptop Price: 25000
ID: 2 Name: TV Price: 50000
ID: 5 Name: Printer Price: 12500

in 运算符类似于 Python 的 in 运算符。对于与列表中名称相匹配的产品名称,使用以下代码 -

The in operator is like Python’s in operator. For name of product matching with names in list, the following code is used −

for product in products.objects(Name__in=['TV', 'Printer']):
print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

Output

ID: 2 Name: TV Price: 50000
ID: 5 Name: Printer Price: 12500

您可以使用以下运算符作为应用于查询的正则表达式的快捷方式 -

You can use following operators as shortcut for regex expressions for applying filter to queries −

exact

string field exactly matches value

iexact

string field exactly matches value (case insensitive)

contains

string field contains value

icontains

string field contains value (case insensitive)

startswith

string field starts with value

istartswith

string field starts with value (case insensitive)

endswith

string field ends with value

iendswith

string field ends with value (case insensitive)

match

performs an $elemMatch so you can match an entire document within an array

例如,以下代码将打印名称中包含 'o' 的产品详细信息 -

For example, the following code prints product details for name containing ‘o’ in name −

for product in products.objects(Name__contains='o'):
   print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

Output

ID: 1 Name: Laptop Price: 25000
ID: 3 Name: Router Price: 2000

在另一个字符串查询示例中,以下代码显示以 'er' 结尾的名称 -

In another example of string query, the following code displays name ending with ‘er’−

for product in products.objects(Name__endswith='er'):
   print ('ID:',product.ProductID, 'Name:',product.Name, 'Price:',product.price)

Output

ID: 3 Name: Router Price: 2000
ID: 4 Name: Scanner Price: 5000
ID: 5 Name: Printer Price: 12500

MongoEngine - QuerySet Methods

QuerySet 对象拥有以下用于查询数据库的有用方法。

The QuerySet object possesses following useful methods for querying the database.

first()

将返回满足查询的第一个文档。以下代码将返回 products 集合中的第一个文档,价格 < 20000。

First document satisfying the query is returned. Following code will return first document in products collection, that has price < 20000.

qset=products.objects(price__lt=20000)
doc=qset.first()
print ('Name:',doc.Name, 'Price:',doc.price)

Output

Name: Router Price: 2000

exclude()

这将导致从查询集中排除提到的字段。此处,Document 类的 to_json() 方法用于获取 Document 的 JSON 化版本。ProductID 字段不会出现在结果中。

This will cause mentioned fields to be excluded from Query Set. Here, to_json() mehod of Document class is used to obtain JSONified version of Document. ProductID field will not appear in the result.

for product in products.objects.exclude('ProductID'):
   print (product.to_json())

Output

{"_id": {"$oid": "5c8dec275405c12e3402423c"}, "Name": "Laptop", "price": 25000}
{"_id": {"$oid": "5c8dec275405c12e3402423d"}, "Name": "TV", "price": 50000}
{"_id": {"$oid": "5c8dec275405c12e3402423e"}, "Name": "Router", "price": 2000}
{"_id": {"$oid": "5c8dec275405c12e3402423f"}, "Name": "Scanner", "price": 5000}
{"_id": {"$oid": "5c8dec275405c12e34024240"}, "Name": "Printer", "price": 12500}

fields()

使用此方法控制加载到查询集中的字段。使用字段名作为关键字参数,并设置为 1 以包含,设置为 0 以排除。

Use this method to manipulate which fields to load in the query set. Use field names as keyword arguments and set to 1 to include, 0 to exclude.

for product in products.objects.fields(ProductID=1,price=1):
print (product.to_json())

Output

{"_id": {"$oid": "5c8dec275405c12e3402423c"}, "ProductID": 1, "price": 25000}
{"_id": {"$oid": "5c8dec275405c12e3402423d"}, "ProductID": 2, "price": 50000}
{"_id": {"$oid": "5c8dec275405c12e3402423e"}, "ProductID": 3, "price": 2000}
{"_id": {"$oid": "5c8dec275405c12e3402423f"}, "ProductID": 4, "price": 5000}
{"_id": {"$oid": "5c8dec275405c12e34024240"}, "ProductID": 5, "price": 12500}

fields() 方法中将字段关键字参数设置为 0 的效果类似于 exclude() 方法。

Setting field keyword argument to 0 in fields() method works similar to exclude() method.

for product in products.objects.fields(price=0):
print (product.to_json())

Output

{"_id": {"$oid": "5c8dec275405c12e3402423c"}, "ProductID": 1, "Name": "Laptop"}
{"_id": {"$oid": "5c8dec275405c12e3402423d"}, "ProductID": 2, "Name": "TV"}
{"_id": {"$oid": "5c8dec275405c12e3402423e"}, "ProductID": 3, "Name": "Router"}
{"_id": {"$oid": "5c8dec275405c12e3402423f"}, "ProductID": 4, "Name": "Scanner"}
{"_id": {"$oid": "5c8dec275405c12e34024240"}, "ProductID": 5, "Name": "Printer"}

only()

这种方法的效果类似于 fields() 方法。只有与关键字参数对应的字段才会出现在查询集中。

Effect of this method is similar to fields() method. Fields corresponding to keyword arguments only will appear in the query set.

for product in products.objects.only('Name'):
print (product.to_json())

Output

{"_id": {"$oid": "5c8dec275405c12e3402423c"}, "Name": "Laptop"}
{"_id": {"$oid": "5c8dec275405c12e3402423d"}, "Name": "TV"}
{"_id": {"$oid": "5c8dec275405c12e3402423e"}, "Name": "Router"}
{"_id": {"$oid": "5c8dec275405c12e3402423f"}, "Name": "Scanner"}
{"_id": {"$oid": "5c8dec275405c12e34024240"}, "Name": "Printer"}

sum()

此方法计算查询集中给定字段的总和。

This method computes sum of given field in the query set.

average()

此方法计算查询集中给定字段的平均值。

This method calculates average of given field in the query set.

avg=products.objects.average('price')
ttl=products.objects.sum('price')
print ('sum of price field',ttl)
print ('average of price field',avg)

Output

sum of price field 94500
average of price field 18900.0

MongoEngine - Sorting

QuerySet 的 order_by() 函数用于按顺序获取查询结果。用法如下:

QuerySet’s order_by() function is used to obtain the query result in a sorted manner. The usage is as follows −

Qset.order_by(‘fieldname’)

默认情况下,排序顺序为升序。对于降序,将 - 号附加到字段名称。例如,按升序获取价格列表:

By default, the sort order is ascending. For descending order, attach – sign to name of field. For example, to get price wise list in ascending order −

from mongoengine import *
con=connect('newdb')

class products (Document):
   ProductID=IntField(required=True)
   company=StringField()
   Name=StringField()
   price=IntField()
for product in products.objects.order_by('price'):
   print ("Name:{} company:{} price:{}".format(product.Name, product.company, product.price))

Output

Name:Router company:Iball price:2000
Name:Scanner company:Cannon price:5000
Name:Printer company:Cannon price:12500
Name:Laptop company:Acer price:25000
Name:TV company:Philips price:31000
Name:Laptop company:Dell price:45000
Name:TV company:Samsung price:50000

以下代码将按 name 降序获取列表:

Following code will get the list in descending order of name −

for product in products.objects.order_by('-Name'):
   print ("Name:{} company:{} price:{}".format(product.Name, product.company, product.price))

Output

Name:TV company:Samsung price:50000
Name:TV company:Philips price:31000
Name:Scanner company:Cannon price:5000
Name:Router company:Iball price:2000
Name:Printer company:Cannon price:12500
Name:Laptop company:Acer price:25000
Name:Laptop company:Dell price:45000

您还可以在多个字段上进行排序。此代码将按升序获取按公司、价格列表。

You can also get sorting done on multiple fields. This code will get you companywise, pricelist in ascending order.

for product in products.objects.order_by('company','price'):
   print ("Name:{} company:{} price:{}".format(product.Name, product.company, product.price))

Output

Name:Laptop company:Acer price:25000
Name:Scanner company:Cannon price:5000
Name:Printer company:Cannon price:12500
Name:Laptop company:Dell price:45000
Name:Router company:Iball price:2000
Name:TV company:Philips price:31000
Name:TV company:Samsung price:50000

MongoEngine - Custom Query Sets

默认情况下,文档类上的 object 属性返回未应用任何筛选器的 QuerySet。但是,您可以在文档上定义类方法来修改查询集。此类方法应该接受两个参数 - doc_cls 和 queryset ,并且需要用 queryset_manager() 装饰它才能被识别。

By default, the objects attribute on a document class returns a QuerySet without applying any filter. However, you can define a classmethod on a document that modifies a queryset. Such a method should accept two arguments – doc_cls and queryset and it needs to be decorated with queryset_manager() in order for it to be recognized.

@queryset_manager
   def qry_method(docs_cls,queryset):
       ….
       ----

在下面的示例中,名为 products 的文档类有一个经过 @queryset_manager 装饰的 expensive_prods() 方法。该方法本身将过滤器应用于查询集,以便仅返回价格 >20000 的对象。此方法现在是默认文档查询,products 类的 objects 属性返回已筛选的文档。

In the following example, the document class called products has an expensive_prods() method which is decorated by @queryset_manager. The method itself applies a filter to queryset such that only objects with price >20000 are returned. This method is now the default document query and objects attribute of products class returns filtered documents.

from mongoengine import *
con=connect('newdb')

class products (Document):
   ProductID=IntField(required=True)
   company=StringField()
   Name=StringField()
   price=IntField()

   @queryset_manager
   def expensive_prods(docs_cls,queryset):
      return queryset.filter(price__gt=20000)
for product in products.expensive_prods():
   print ("Name:{} company:{} price:{}".format(product.Name, product.company, product.price))

Output

Name:Laptop company:Acer price:25000
Name:TV company:Samsung price:50000
Name:TV company:Philips price:31000
Name:Laptop company:Dell price:45000

如果您希望自定义过滤文档的方法,请首先声明 QuerySet 类的子类,并将其用作元数据中的 queryset_class 属性的值。

If you wish to customize methods for filtering documents, first declare a subclass of QuerySet class, and use it as value of queryset_class property in meta dictionary.

以下示例使用 MyQuerySet 类作为自定义查询集的定义。此类中的 myqrymethod() 过滤名称字段以“er”结尾的文档。在 products 类中,meta 属性引用此查询集子类,用作 queryset_class 属性的值。

The example below uses MyQuerySet class as definition of custom queryset. The myqrymethod() in this class filters the documents whose name field ends with ‘er’. In products class, meta attribute refers to this queryset subclass is used as value of queryset_class property.

from mongoengine import *
con=connect('newdb')
class MyQuerySet(QuerySet):
   def myqrymethod(self):
      return self.filter(Name__endswith='er')
class products (Document):
   meta = {'queryset_class': MyQuerySet}
   ProductID=IntField(required=True)
   company=StringField()
   Name=StringField()
   price=IntField()
for product in products.objects.myqrymethod():
   print ("Name:{} company:{} price:{}".format(product.Name, product.company, product.price))

Output

Name:Router company:Iball price:2000
Name:Scanner company:Cannon price:5000
Name:Printer company:Cannon price:12500

MongoEngine - Indexes

索引的集合导致更快的查询处理。默认情况下,每个集合都自动在 _id 字段上建立索引。此外,您可以在一个或多个字段上创建索引。

An indexed collection results in faster processing of queries. By default, every collection is automatically indexed on _id field. In addition, you can create index on one or more fields.

使用 Compass,我们可以非常轻松地构建索引。单击下图所示的 Indexes 选项卡上的 CREATE INDEX 按钮:

Using Compass, we can build index very easily. Click on CREATE INDEX button on Indexes tab as shown in figure below−

indexes

将出现一个如所示的对话框。选择索引的名称、要建立索引的字段、索引的顺序(升序或降序)和其他选项。

A dialog box appears as shown. Choose name of index, field on which to index, order of index (ascending or descending) and other options.

create indexes

在使用 MongoEngine 时,索引是通过指定 Document 类定义的元数据中的“indexes”键创建的。

While using MongoEngine, indexes are created by specifying ‘indexes’ key in meta dictionary of definition of Document class.

indexes 属性的值是字段列表。在以下示例中,我们要求 student 集合中的文档按 name 字段建立索引。

Value of indexes property is a list of fields. In the following example, we ask documents in student collection be indexed according to name field.

from mongoengine import *
con=connect('mydata')
class student(Document):
   name=StringField(required=True)
   course=StringField()
   meta = {'indexes':['name']}

s1=student()
s1.name='Avinash'
s1.course='DataScience'
s1.save()
s2=student()
s2.name='Anita'
s2.course='WebDesign'
s2.save()

默认情况下,索引顺序为升序。可以通过对升序添加“+”,对降序添加“-”来指定顺序。

By default, indexing order is ascending. Order may be specified by prepending ‘+’ for ascending or ‘-‘ for descending order.

要创建复合索引,请使用字段名称的元组,可以选择附加 + 或 - 符号来指示排序顺序。

To create compound index, use a tuple of field names, optionally having + or – symbol attached to indicate sort order.

在以下示例中,student 文档类包含对名称和课程的复合索引的定义(注意 - 以课程字段为前缀的符号,表示索引按名称升序和课程降序构建。

In the following example, student document class contains definition of compound index on name and course (note - symbol prefixed to course field which means index is built namewise ascending and coursewise descending order.

from mongoengine import *
con=connect('mydata')

class student(Document):
   name=StringField(required=True)
   course=StringField()
   meta = {'indexes':[('name','-course')]}

s1=student()
s1.name='Avinash'
s1.course='DataScience'
s1.save()
s2=student()
s2.name='Anita'
s2.course='WebDesign'
s2.save()

MongoDB Compass 将如下所示显示索引 -

MongoDB Compass will show indexes as below −

value of indexes

“索引”的值可能是各种选项的字典,如下所示:

Value of ‘indexes’ may be a dictionary of various options as below −

fields

The fields to index.

cls

If allow_inheritance is turned on, you can configure whether the index should have the _cls field added automatically.

sparse

Whether the index should be sparse.

unique

Whether the index should be unique.

expireAfterSeconds

automatically expire data from a collection by setting the time in seconds

name

Allows you to specify a name for the index

collation

Allows to create case insensitive indexes

以下示例在 name 字段上创建索引,该索引在 3600 秒后过期。

Following example creates index on name field that expires after 3600 seconds.

from mongoengine import *
con=connect('mydata')

class student(Document):
   name=StringField(required=True)
   course=StringField()
   meta = {'indexes':[{
            'fields': ['name'],
            'expireAfterSeconds': 3600
           }
    ]
}

要指定文本索引,请使用“$”符号作为字段名称前缀,对于哈希索引,请使用“#”作前缀。

To specify text index, prefix field name with ‘$’ sign and for hashed index, use ‘#’ as prefix.

如此指定的索引在向集合中添加文档时会自动创建。要禁用自动创建,请在元属性中将 “ auto_create_index ” 设置为 False。

Indexes so specified are created automatically as documents are added in the collection. To disable automatic creation, set ‘auto_create_index’ to False in meta attribute.

我们有带有 Document 类的方法 list_indexes() ,它显示可用索引的列表。

We have list_indexes() method with Document class that displays list of available indexes.

print (student.list_indexes())

[[('name', 1)], [('_id', 1)]]

要在元字典中不存在的字段上创建索引,请使用 create_index() 方法。以下代码将在 course 字段上创建索引 -

To create index on a field not in the meta dictionary, use create_index() method. The following code will create index on course field −

class student(Document):
name=StringField(required=True)
course=StringField()
meta = {'indexes':[{
          'fields': ['name'],
          'expireAfterSeconds': 3600
        }
]}
student.create_index(['course'])

MongoEngine - Aggregation

术语 “ aggregation ” 用于对数据进行处理并返回计算结果的操作。对集合中一个或多个文档字段求和、计数和平均值可称为聚合函数。

The term ‘aggregation’ is used for the operation that processes data and returns computed result. Finding sum, count and average on one or more fields of documents in a collection can be called as aggregation functions.

MongoEngine 提供了 aggregate() 函数,该函数封装了 PyMongo 的聚合框架。聚合操作使用集合作为输入,并返回一个或多个文档作为结果。

MongoEngine provides aggregate() function that encapsulates PyMongo’s aggregation framework. Aggregation operation uses a collection as input and returns one or more documents as a result.

MongoDB 使用数据处理管道这一概念。一个 pipeline 可以有多个阶段。基本阶段提供了提供过滤器和像查询一样运作的内容。其他阶段提供了按一个或多个字段进行分组和/或排序、字符串连接任务、数组聚合工具等的工具。

MongoDB uses concept of data processing pipelines. A pipeline can have multiple stages. Basic stage provides that provide filter and operate like queries. Others provide tools for grouping and/or sorting by one or more fields, string concatenation tasks, array aggregation tools, etc.

在 MongoDB 管道创建中定义了以下阶段 -

Following stages are defined in MongoDB pipeline creation −

Name

Description

$project

Reshapes each document in the stream, by adding new fields or removing existing fields.

$match

Filters the document stream to allow only matching documents to pass unmodified into the next stage. $match uses standard MongoDB queries.

$redact

Reshapes each document by restricting the content for each document based on information stored in the documents themselves.

$limit

Limits documents to be passed unmodified to the pipeline

$skip

Skips the first n documents and passes the remaining documents unmodified to the pipeline.

$group

Groups input documents by a given identifier expression and applies the accumulator expressions to each group. The output documents only contain the identifier field and accumulated fields.

$sort

Reorders the document stream by a specified sort key.

$out

Writes the resulting documents of the aggregation pipeline to a collection.

聚合表达式使用字段路径来访问输入文档中的字段。要指定字段路径,请在字段名称前添加一个美元符号 $。表达式可以使用一个或多个布尔运算符($and、$or、$not)和比较运算符($eq、$gt、$lt、$gte、$lte 和 $ne)。

Aggregation expressions use field path to access fields in the input documents. To specify a field path, use a string that prefixes with a dollar sign $$$ the field name. Expression can use one or more Boolean operators ($and, $or, $not) and comparison operators ($eq, $gt, $lt, $gte, $lte and $ne).

以下算术表达式也用于聚合 −

Following arithmetic expressions are also used for aggregation −

$add

Adds numbers to return the sum. Accepts any number of argument expressions

$subtract

Returns the result of subtracting the second value from the first

$multiply

Multiplies numbers to return the product. Accepts any number of argument expressions

$divide

Returns the result of dividing the first number by the second. Accepts two argument expressions

$mod

Returns the remainder of the first number divided by the second. Accepts two argument expressions

以下字符串表达式也可用于聚合中 −

Following string expression can also be used in aggregation −

$concat

Concatenates any number of strings

$substr

Returns a substring of a string, starting at a specified index position up to a specified length

$toLower

Converts a string to lowercase. Accepts a single argument expression

$toUpper

Converts a string to uppercase. Accepts a single argument expression

$strcasecmp

Performs string comparison and returns 0 if two strings are equivalent, 1 if first is greater than second, and -1 if first string is less than second

为了演示 aggregate() 函数在 MongoEngine 中的工作方式,我们首先来定义一个名为 orders 的文档类。

To demonstrate how aggregate() function works in MongoEngine, let us first define a Document class called orders.

from mongoengine import *
con=connect('mydata')

class orders(Document):
   custID = StringField()
   amount= IntField()
   status = StringField()

然后,我们在 orders 集合中添加以下文档 −

We then add following documents in orders collection −

_id

custID

amount

status

ObjectId("5eba52d975fa1e26d4ec01d0")

A123

500

A

ObjectId("5eba536775fa1e26d4ec01d1")

A123

250

A

ObjectId("5eba53b575fa1e26d4ec01d2")

B212

200

D

ObjectId("5eba540e75fa1e26d4ec01d3")

B212

400

A

aggregate() 函数用于查找仅当 status 等于 'A' 时每个 custID 的 amount 字段的和。于是,管道建立如下。

The aggregate() function is to be used to find sum of amount field for each custID only when status equals ‘A’. Accordingly, the pipeline is constructed as follows.

管道中的第一阶段使用 $match 来筛选 status='A' 的文档。第二阶段使用 $group 标识符对 CustID 上的文档进行分组并对 amount 求和。

First stage in pipeline uses $match to filter documents with status=’A’. Second stage uses $group identifier to group documents on CustID and performs sum of amount.

 pipeline = [
{"$match" : {"status" : "A"}},
{"$group": {"_id": "$custID", "total": {"$sum": "$amount"}}}
]

此管道现在用作 aggregate() 函数的参数。

This pipeline is now used as argument to aggregate() function.

docs = orders.objects().aggregate(pipeline)

我们可以使用 for 循环对文档游标进行迭代。完整的代码如下所示 −

We can iterate over the document cursor with a for loop. The complete code is given below −

from mongoengine import *
con=connect('mydata')

class orders(Document):
   custID = StringField()
   amount= IntField()
   status = StringField()

pipeline = [
   {"$match" : {"status" : "A"}},
   {"$group": {"_id": "$custID", "total": {"$sum": "$amount"}}}
   ]
docs = orders.objects().aggregate(pipeline)
for doc in docs:
   print (x)

对于给定的数据,将生成以下输出 −

For the given data, the following output is generated −

{'_id': 'B212', 'total': 400}
{'_id': 'A123', 'total': 750}

MongoEngine - Advanced Queries

为了提高在文档中检索字段子集的效率,请使用 Objects 属性的 only() 方法。这将显著提高性能,特别是对于极大长度的字段,例如 ListField。将所需的字段传递给 only() 函数。如果在执行 only() 查询后访问了其他字段,则返回默认值。

In order to get more efficiency in retrieving a subset of fields in a document, use only() method of Objects attribute. This will significantly improve performance especially for fields with extremely large length such as ListField. Pass the required field to only() function. If other fields are accessed after executing only() query, default value is returned.

from mongoengine import *
con=connect('newdb')
class person (Document):
name=StringField(required=True)
city=StringField(default='Mumbai')
pin=IntField()
p1=person(name='Himanshu', city='Delhi', pin=110012).save()
doc=person.objects.only('name').first()
print ('name:',doc.name)
print ('city:', doc.city)
print ('PIN:', doc.pin)

Output

name: Himanshu
city: Mumbai
PIN: None

Note − 使用 city 属性的值作为默认值。由于未为 PIN 指定默认值,因此打印 None。

Note − The value of city attribute is used as default. As default is not specified for PIN, it prints None.

如果您需要丢失的字段,可以调用 reload() 函数。

You may call reload() function if you need missing fields.

当文档类具有 ListField 或 DictField 时,在对其进行迭代时,任何 DBREf 对象都会自动取消引用。为了进一步提高效率,特别是如果文档具有 ReferenceField,可以使用 select_related() 函数对查询数量进行限制,该函数会将 QuerySet 转换为列表并取消引用。

When a document class has a ListField or DictField, while iterating through it, any DBREf objects are automatically dereferenced. To increase the efficiency further, especially if the document has ReferenceField, number of queries can be limited by using select_related() function which converts QuerySet in a list and effects dereferencing.

MongoEngine API 包含 Q 类,该类可用于构建由多个约束条件组成的复杂查询。Q 表示查询的一部分,该部分可以通过关键字参数语法和二进制 & 和 | 运算符来初始化。

MongoEngine API contains Q class which is useful for constructing advanced queries consisting of number of constraints. Q represents a part of query which can be initialized by keyword argument syntax and binary & and | operators.

person.objects(Q(name__startswith=’H’) &Q(city=’Mumbai’))

MongoEngine - Document Inheritance

可以为任何用户定义的文档类定义一个派生类。派生类可能会根据需要添加其他字段。但是,由于此类不是 Document 类的直接子类,因此它不会创建新集合,而是将其对象存储在父类使用的集合中。在父类中,meta 属性 ' allow_inheritance 在以下示例中,我们首先将 employee 定义为文档类,并将 allow_inheritance 设置为 true。salary 类是从 employee 派生的,它添加了另外两个字段 dept 和 sal。Employee 及 salary 类的对象存储在 employee 集合中。

It is possible to define an inherited class of any user defined Document class. The inherited class may add extra fields if required. However, since such as a class is not a direct subclass of Document class, it will not create a new collection, instead its objects are stored in a collection used by its parent class. In the parent class, meta attribute ‘allow_inheritance the following example, we first define employee as a document class and set allow_inheritance to true. The salary class is derived from employee, adding two more fields dept and sal. Objects of Employee as well as salary classes are stored in employee collection.

在以下示例中,我们首先将 employee 定义为文档类,并将 allow_inheritance 设置为 true。salary 类是从 employee 派生的,它添加了另外两个字段 dept 和 sal。Employee 及 salary 类的对象存储在 employee 集合中。

In the following example, we first define employee as a document class and set allow_inheritance to true. The salary class is derived from employee, adding two more fields dept and sal. Objects of Employee as well as salary classes are stored in employee collection.

from mongoengine import *
con=connect('newdb')
class employee (Document):
name=StringField(required=True)
branch=StringField()
meta={'allow_inheritance':True}
class salary(employee):
dept=StringField()
sal=IntField()
e1=employee(name='Bharat', branch='Chennai').save()
s1=salary(name='Deep', branch='Hyderabad', dept='Accounts', sal=25000).save()

我们可以验证 employee 集合中存储了两个文档,如下所示 −

We can verify that two documents are stored in employee collection as follows −

{
"_id":{"$oid":"5ebc34f44baa3752530b278a"},
"_cls":"employee",
"name":"Bharat",
"branch":"Chennai"
}
{
"_id":{"$oid":"5ebc34f44baa3752530b278b"},
"_cls":"employee.salary",
"name":"Deep",
"branch":"Hyderabad",
"dept":"Accounts",
"sal":{"$numberInt":"25000"}
}

请注意,为了识别相应的文档类,MongoEngine 添加了一个 “_cls” 字段,并将它的值设置为 “employee” 和 “employee.salary”。

Note that, in order to identify the respective Document class, MongoEngine adds a “_cls” field and sets its value as "employee" and "employee.salary".

如果您想为一群文档类提供额外的功能,但没有继承的开销,那么您可以首先创建一个 abstract 类,然后从同一类派生一个或多个类。要使类抽象,将 meta 属性 'abstract' 设置为 True。

If you want to provide extra functionality to a group of Document classes, but without overhead of inheritance, you can first create an abstract class and then derive one or more classes from the same. To make a class abstract, meta attribute ‘abstract’ is set to True.

from mongoengine import *
con=connect('newdb')

class shape (Document):
   meta={'abstract':True}
   def area(self):
      pass

class rectangle(shape):
   width=IntField()
   height=IntField()
   def area(self):
      return self.width*self.height

r1=rectangle(width=20, height=30).save()

MongoEngine - Atomic Updates

原子性是 ACID 事务属性之一。数据库事务必须是不可分割和不可简化的,以便要么完全发生,要么根本不发生。此属性称为原子性。MongoDB 仅对单一文档支持原子性,而不是多文档事务。

Atomicity is one of the ACID transaction properties. A database transaction has to be indivisible and irreducible so that it either occurs completely or doesn’t occur at all. This property is called Atomicity. MongoDB supports Atomicity only on single documents and not on multi-document transactions.

MongoEngine 为查询集的原子更新提供了以下方法。

MongoEngine provides the following methods for atomic updates on a queryset.

update_one() - 覆盖或添加与查询匹配的第一条文档。

update_one() − Overwrites or adds first document matched by query.

update() - 对与查询匹配的字段执行原子更新。

update() − Performs atomic update on fields matched by query.

modify() - 更新文档并将其返回。

modify() − Update a document and return it.

以下的修改器可能会与这些方法一起使用。(这些修改器在字段之前,而不是之后)。

Following modifiers may be used with these methods. (These modifiers come before the field, not after).

set

set a particular value

unset

delete a particular value

inc

increment a value by a given amount

dec

decrement a value by a given amount

push

append a value to a list

push_all

append several values to a list

pop

remove the first or last element of a list depending on the value

pull

remove a value from a list

pull_all

remove several values from a list

add_to_set

add value to a list only if its not in the list already

以下是一个原子更新的示例,我们首先创建一个名为测试的文档类,并在其中添加一个文档。

The following is an example of atomic update, we first create a Document class called tests and add a document in it.

from mongoengine import *
con=connect('newdb')

class tests (Document):
   name=StringField()
   attempts=IntField()
   scores=ListField(IntField())

t1=tests()
t1.name='XYZ'
t1.attempts=0
t1.scores=[]
t1.save()

让我们使用 update_one() 方法将 name 字段从 XYZ 更新为 MongoDB。

Let us use update_one() method to update name field from XYZ to MongoDB.

tests.objects(name='XYZ').update_one(set__name='MongoDB')

push 修改器用于在 ListField(scores)中添加数据。

The push modifier is used to add data in ListField (scores).

tests.objects(name='MongoDB').update_one(push__scores=50)

若要将 attempts 字段增加 1,我们可以使用 inc 修改器。

To increment attempts field by one, we can use inc modifier.

tests.objects(name='MongoDB').update_one(inc__attempts=1)

更新后的文档如下所示 -

The updated document looks as follows −

{
"_id":{"$oid":"5ebcf8d353a48858e01ced04"},
"name":"MongoDB",
"attempts":{"$numberInt":"1"},
"scores":[{"$numberInt":"50"}]
}

MongoEngine - Javascript

MongoEngine 的 QuerySet 对象具有 exec_js() 方法,该方法允许在 MongoDB 服务器上执行 Javascript 函数。此函数处理以下参数 -

QuerySet object of MongoEngine has exec_js() method that allows execution of a Javascript function on MongoDB server. This function processes the following arguments −

exec_js(code, *field_names, **options)

其中,

Where,

  1. code − a string containing Javascript code to execute

  2. fields − to be used in your function, which will be passed as arguments

  3. options − options that you want available to the function (accessed in Javascript through the options object)

此外,还可以按以下方式将一些其他变量提供给函数作用域:

In addition, some more variables are also made available to the function’s scope as given below −

  1. collection − name of the collection corresponding to the Document class. This should be used to get the Collection object from db in Javascript code.

  2. query − the query that has been generated by the QuerySet object; passed into the find() method on a Collection object in the Javascript function.

  3. options − an object containing the keyword arguments passed into exec_js().

请注意,MongoEngine 文档类中的属性在数据库中使用不同的名称(使用 Field 构造函数中的 db_field 关键字参数设置)。

Note that attributes in MongoEngine document class may use different names in the database (set using the db_field keyword argument to a Field constructor).

class BlogPost(Document):
title = StringField(db_field='doctitle')

为此,存在一种机制,可以在 Javascript 代码中将 MongoEngine 字段属性替换为数据库字段名。

For this purpose, a mechanism exists for replacing MongoEngine field attribute with the database field names in Javascript code.

当在集合对象中访问一个字段时,请使用方括号符号,并在 MongoEngine 字段名前加上一个波形符号 (~)。波形符号后的字段名将转换为在数据库中使用的名称。

When accessing a field on a collection object, use square-bracket notation, and prefix the MongoEngine field name with a tilde (~) symbol. The field name that follows the tilde will be translated to the name used in the database.

document': doc[~title];

请注意,当 Javascript 代码引用嵌入式文档中的字段时,应在嵌入式文档中的字段名之前使用嵌入式文档字段的名称,后跟一个点。

Note that when Javascript code refers to fields on embedded documents, the name of the EmbeddedDocumentField, followed by a dot, should be used before the name of the field on the embedded document.

MongoEngine - GridFS

在 MongoDB 中,使用 GridFS 规范存储大小超过 16 MB 的文件。一个文件被分成多个块,每个块的默认大小为 255KB。大块可以尽可能大。GridFS 使用两个集合,一个用于块,另一个用于元数据。

In MongoDB, the files with size larger than 16 MB are stored using GridFS specifications. A file is divided into multiple chunks each with a default size of 255KB. Large chunk may be as large as necessary. GridFS uses two collections, one for chunks and other for metadata.

如果您想访问 GridFS 存储的任何文件,而不必将整个文件加载到内存中,可以使用 GridFS。

GridFS may be used to store any file if you want to access it without having to load it entirely in the memory.

MongoEngine API 通过 FileField 对象支持 GridFS。使用此对象,可以插入和检索数据。FileField 对象的 put() 方法有助于将文件写为 Document 的一部分。

MongoEngine API supports GridFS through FileField object. Using this object, it is possible to insert and retrieve data. The FileField object’s put() method helps writing the file as a part of Document.

from mongoengine import *
con=connect('newdb')

class lang (Document):
   name=StringField()
   developer=StringField()
   logo=FileField()

l1=lang()
l1.name='Python'
l1.developer='Van Rossum'
f=open('pylogo.png','rb')
l1.logo.put(f,content_type='image/png')
l1.save()

可以使用 Python 文件对象中的 read() 方法检索 FileField 的内容。

Contents of FileField can be retrieved by read() method of Python’s File object.

logo = l1.logo.read()

另外还有 delete() 方法,用于删除存储的文件。

There is also delete() method to delete the stored file.

l1 = lang.objects(name='Python').first()
l1.logo.delete()
l1.save()

请注意,FileField 仅将文件 ID 存储在单独的 GridFS 集合中。因此 delete() 方法不会实际删除文件。

Note that the FileField stores only the ID of file in a separate GridFS collection. Hence delete() method does not delete the file physically.

replace() 方法有助于将文件引用替换为另一个文件。

The replace() method helps in replacing reference of file with another file.

l1 = lang.objects(name='Python').first()
f=open('newlogo.png','rb')
l1.logo.replace(f,content_type='image/png')
l1.save()

MongoEngine - Signals

信号是由发送方对象发送的事件,任意数量的接收方对象可以订阅此类事件。信号接收方可以订阅特定的发送方,或者可以接收来自多个发送方的信号。

Signals are events dispatched by a sender object, any number of receiver objects can subscribe to such events. A signal receiver can subscribe to a specific sender or may receive signals from many senders.

在 MongoEngine 中,信号处理由 blinker 库支持,这意味着你需要使用 pip 实用程序来安装它。mongoengine.signals 模块定义了以下信号 −

In MongoEngine, signal handling is supported by blinker library, which means you need to install it using pip utility. The mongoengine.signals module has the definitions of following signals −

pre_init

Called during the creation of a new Document or EmbeddedDocument instance and executed after the constructor arguments have been collected but before any additional processing has been done to them.

post_init

Called after all processing of a new Document or EmbeddedDocument instance has been completed.

pre_save

Called within save() prior to performing any actions.

pre_save_post_validation

Called within save() after validation has taken place but before saving.

post_save

Called within save() after most actions (validation, insert/update) have completed successfully. An additional Boolean keyword argument is passed to indicate if the save was an insert or an update.

pre_delete

Called within delete() prior to attempting the delete operation.

post_delete

Called within delete() upon successful deletion of the record.

pre_bulk_insert

Called after validation of the documents to insert, but prior to any data being written.

post_bulk_insert

Called after a successful bulk insert operation. An additional Boolean argument, loaded, identifies the contents of documents as either Document instances when True or a list of primary key values for the inserted records if False.

然后将事件处理程序函数附加到 Document 类。请注意, EmbeddedDocument 仅支持 pre/post_init 信号。pre/post_save 等只能附加到 Document 类。

An event handler function is then attached to Document class. Note that EmbeddedDocument only supports pre/post_init signals. pre/post_save, etc., should be attached to Document’s class only.

你还可以使用装饰器快速创建多个信号并将它们作为类装饰器附加到 Document 或 EmbeddedDocument 子类。

You can also use a decorator to quickly create a number of signals and attach them to your Document or EmbeddedDocument subclasses as class decorators.

在以下示例中,用作信号处理程序的演示,我们还使用 Python 的标准库模块——记录并设置记录级别以进行调试。

In the following example, used as demonstration of signal handlers, we also use Python’s standard library module – logging and set the logging level to debug.

from mongoengine import *
from mongoengine import signals
import logging
logging.basicConfig(level=logging.DEBUG)

然后,我们编写一个文档类,以便在 newdb 数据库中创建相应的集合。在类中,定义了两个类的方法 pre_save() 和 post_save(),目的是在将文档保存在 Author 集合中之前和之后调用。

We then write a document class so that corresponding collection is created in newdb database. Inside the class, two class mehods pre_save() and post_save() methods are defined which are intended to be invoked before and after a document is saved in Author collection.

class Author(Document):
   name = StringField()

   def __unicode__(self):
      return self.name

   @classmethod
   def pre_save(cls, sender, document, **kwargs):
      logging.debug("Pre Save: %s" % document.name)

   @classmethod
   def post_save(cls, sender, document, **kwargs):
      logging.debug("Post Save: %s" % document.name)
      if 'created' in kwargs:
         if kwargs['created']:
            logging.debug("Created")
         else:
            logging.debug("Updated")

这两个类方法都被定义为带有 classname、发送者对象和带有可选关键字参数列表的文档的参数。

Both the class methods are defined with arguments for classname, sender object and document with optional list of keyword arguments.

最后,我们注册信号处理程序。

Finally, we register the signal handlers.

signals.pre_save.connect(Author.pre_save, sender=Author)
signals.post_save.connect(Author.post_save, sender=Author)

当我们创建 Document 子类的实例时,控制台日志将显示由相应事件处理程序处理的 pre 和 post 保存信号。

As we create an instance of Document subclass, the console log will show the pre and post save signals being processed by respective event handlers.

Author(name="Lathkar").save()

Python 控制台按如下所示报告日志 −

Python console reports the log as shown below −

DEBUG:root:Pre Save: Lathkar
DEBUG:root:Post Save: Lathkar
DEBUG:root:Created

MongoDB 支持使用可以对字符串内容执行文本搜索的查询运算符。如前所述,要设置文本索引,请使用 $ 符号作为索引的前缀名。对于文本索引,索引字段的权重表示相对于其他索引字段在文本搜索分数方面的字段的重要程度。你还可以再类的元字典中指定默认语言。

MongoDB supports use of query operators that can perform text search on a string content. As described earlier, to set a text index prefix name of index with $ symbol. For a text index, the weight of an indexed field denotes the significance of the field relative to the other indexed fields in terms of the text search score. You can also specify default language in meta dictionary of the class.

支持的语言列表位于 https://docs.mongodb.com/manual/reference/text-search-languages/ 。MongoEngine API 由 QuerySet 对象的 search_text() 方法组成。在索引字段中要搜索的字符串作为参数给出。

List of supported languages can be found at https://docs.mongodb.com/manual/reference/text-search-languages/ MongoEngine API consists of search_text() method for QuerySet object. The string to be searched in indexed fields is given as argument.

在以下示例中,我们首先定义一个名为 lang 的 Document 类,其中包含两个字符串字段,即语言的名称及其特征。我们还在两个字段上分别创建了具有相应权重的索引。

In the following example, we first define a Document class called lang with two string fields, name of language and its features. We also create indexes on both fields with respective weights.

from mongoengine import *
con=connect('newdb')

class lang (Document):
   name=StringField()
   features=StringField()
   meta = {'indexes': [
      {'fields': ['$name', "$features"],
         'default_language': 'english',
         'weights': {'name': 2, 'features': 10}
      }]
   }

l1=lang()
l1.name='C++'
l1.features='Object oriented language for OS development'
l1.save()
l2=lang()
l2.name='Python'
l2.features='dynamically typed and object oriented for data science, AI and ML'
l2.save()
l3=lang()
l3.name='HTML'
l3.features='scripting language for web page development'
l3.save()

为了对单词“oriented”执行搜索,我们使用 search_text() 方法,如下所示:

In order to perform search for word ‘oriented’, we employ search_text() method as follows −

docs=lang.objects.search_text('oriented')
for doc in docs:
   print (doc.name)

上述代码的输出是其描述中包含单词“oriented”(在本例中为“Python”和“C++”)的语言的名称。

Output of the above code will be names of languages in whose description the word ‘oriented’ occurs (‘Python and ‘C++’ in this case).

MongoEngine - Extensions

MongoEngine 与以下库完美集成:

MongoEngine integrates beautifully with the following libraries −

marshmallow_mongoengine

marshmallow 是一款与 ORM/ODM/框架无关的序列化/反序列化库,用于在复杂数据类型(例如对象)和原生 Python 数据类型之间进行转换。使用 MongoEngine 的此扩展,我们可以轻松地执行序列化/反序列化操作。

marshmallow is an ORM/ODM/framework independent serialization/deserialization library for converting complex datatypes, such as objects, to and from native Python datatypes. Using this extension of MongoEngine, we can easily perform serialize/deserialize operations.

首先,像往常一样创建 Document 类,如下所示:

First, create a Document class as usual as follows −

import mongoengine as me
class Book(me.Document):
title = me.StringField()

然后使用以下代码生成 marshmallow 模式:

Then generate marshmallow schema with the code below −

from marshmallow_mongoengine import ModelSchema
class BookSchema(ModelSchema):
   class Meta:
      model = Book

b_s = BookSchema()

使用如下代码保存文档:

Save a document using the code:

book = Book(title='MongoEngine Book').save()

并使用 dump(0 执行序列化/反序列化,并使用以下代码加载():

And perform serialization/deserialization using dump(0 and load() using the code below −

data = b_s.dump(book).data
b_s.load(data).data

Flask-MongoEngine

这是一个为 MongoEngine 提供集成的 Flask 扩展。该库可以轻松处理应用程序的 MongoDB 数据库连接管理。您还可以将 WTForms 作为模型的模型表单使用。

This is a Flask extension that provides integration with MongoEngine. Connection management of MongoDB database for your app is handled easily by this library. You can also use WTForms as model forms for your models.

安装 flask-mongoengine 包后,使用以下设置初始化 Flask 应用程序:

After installation of flask-mongoengine package, initialize flask app with the following settings −

from flask import Flask
from flask_mongoengine import MongoEngine

app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
   'db': 'mydata',
   'host': 'localhost',
   'port':27017
}
db = MongoEngine(app)

然后使用以下代码定义 Document 子类:

Then define a Document sub class using the below code −

class book(me.Document):
name=me.StringField(required=True)

声明上述类的对象,并在访问特定路由时调用 save() 方法。

Declare an object of above class and call save() method when a particular route is visited.

@app.route('/')
def index():
b1=book(name='Introduction to MongoEngine')
b1.save()
return 'success'

extras-mongoengine

此扩展包含其他字段类型和任何其他奥术。

This extension contains additional Field Types and any other wizardry.

Eve-MongoEngine

Eve 是一个为人类设计的开源 Python REST API 框架。它允许轻松构建和部署高度可自定义且功能齐全的 RESTful Web 服务。

Eve is an open source Python REST API framework designed for human beings. It allows to effortlessly build and deploy highly customizable, fully featured RESTful Web Services.

Eve 由 Flask 和 Cerberus 提供支持,并提供对 MongoDB 数据存储的本机支持。Eve-MongoEngine 为 Eve 提供了 MongoEngine 集成。

Eve is powered by Flask and Cerberus and it offers native support for MongoDB data stores. Eve-MongoEngine provides MongoEngine integration with Eve.

使用以下代码安装和导入该扩展:

Install and import the extension using the code below −

import mongoengine
from eve import Eve
from eve_mongoengine import EveMongoengine

配置设置并初始化 Eve 实例。

Configure the settings and initialize the Eve instance.

my_settings = {
'MONGO_HOST': 'localhost',
'MONGO_PORT': 27017,
'MONGO_DBNAME': 'eve_db'
app = Eve(settings=my_settings)
# init extension
ext = EveMongoengine(app)

按所示定义一个文档类:

Define a Document class as shown below −

class Person(mongoengine.Document):
name = mongoengine.StringField()
age = mongoengine.IntField()

添加模型并运行应用程序,最后使用以下代码:

Add the model and run the application, finally using the below code −

ext.add_model(Person)
app.run()

Django-MongoEngine

此扩展的目的是将 MongoEngine 与 Django API 集成在一起,这是一个非常流行的 Python Web 开发框架。此项目仍在开发中。

This extension aims to integrate MongoEngine with Django API, a very popular Python web development framework. This project is still under development.