Docs HomeMongoDB Manual

Field Encryption and Queryability字段加密和可查询性

Queryable Encryption with equality queries is generally available (GA) in MongoDB 7.0 and later. 具有相等查询的可查询加密在MongoDB 7.0及更高版本中通常可用(GA)。The Queryable Encryption Public Preview, released in version 6.0, is no longer supported. Data encrypted using the Public Preview is incompatible with the feature release. 不再支持6.0版本中发布的“可查询加密预览”。使用公共预览加密的数据与功能版本不兼容。For more information, see Compatibility Changes in MongoDB 7.0.有关更多信息,请参阅MongoDB 7.0中的兼容性更改

Overview概述

Learn about the following Queryable Encryption topics:了解以下可查询加密主题:

  • Considerations when enabling queries on an encrypted field.在加密字段上启用查询时的注意事项。
  • How to specify fields for encryption.如何指定要加密的字段。
  • How to configure an encrypted field so that it is queryable.如何配置加密字段以使其可查询。
  • Query types and which ones you can use on encrypted fields.查询类型以及可以在加密字段上使用的查询类型。
  • How to optimize query performance on encrypted fields.如何优化加密字段的查询性能。

Considerations when Enabling Querying启用查询时的注意事项

When you use Queryable Encryption, you can choose whether to make an encrypted field queryable. 使用可查询加密时,可以选择是否使加密字段可查询。If you don't need to perform CRUD operations that require you to query an encrypted field, you may not need to enable querying on that field. 如果不需要执行要求查询加密字段的CRUD操作,则可能不需要对该字段启用查询。You can still retrieve the entire document by querying other fields that are queryable or not encrypted.您仍然可以通过查询其他可查询或未加密的字段来检索整个文档。

When you make encrypted fields queryable, Queryable Encryption creates an index for each encrypted field, which can make write operations on that field take longer. When a write operation updates an indexed field, MongoDB also updates the related index.当您使加密字段可查询时,可查询加密会为每个加密字段创建一个索引,这可能会使该字段的写入操作耗时更长。当写操作更新索引字段时,MongoDB也会更新相关的索引。

When you create an encrypted collection, MongoDB creates two metadata collections, increasing the storage space requirements.创建加密集合时,MongoDB会创建两个元数据集合,从而增加存储空间需求。

Specify Fields for Encryption指定加密字段

Queryable Encryption allows you to specify which fields you want to automatically encrypt in your MongoDB document.可查询加密允许您指定要在MongoDB文档中自动加密的字段。

Important

You can specify any field for encryption except the _id field.除了_id字段之外,您可以指定任何用于加密的字段。

To specify fields for encryption and querying, define a JSON schema that includes the following properties:要指定用于加密和查询的字段,请定义包含以下属性的JSON模式:

Key NameType类型Required必需
pathStringRequired必要的
bsonTypeStringRequired必要的
keyIdBinaryOptional.可选的。Use only if you want to use explicit encryption, which requires you to generate a key for each field in advance.仅当您希望使用显式加密时使用,这需要您提前为每个字段生成一个键。
queriesObjectOptional.可选的。Omit unless you want to be able to query the field.省略,除非您希望能够查询字段。

Example实例

This example shows how to create a JSON schema that specifies which fields Queryable Encryption should automatically encrypt.此示例显示如何创建JSON模式,该模式指定可查询加密应自动加密哪些字段。

Consider the following document that contains personally identifiable information (PII), credit card information, and sensitive medical information:考虑以下包含个人身份信息(PII)、信用卡信息和敏感医疗信息的文档:

{
"firstName": "Jon",
"lastName": "Snow",
"patientId": 12345187,
"address": "123 Cherry Ave",
"medications": [
"Adderall",
"Lipitor"
],
"patientInfo": {
"ssn": "921-12-1234",
"billing": {
"type": "visa",
"number": "1234-1234-1234-1234"
}
}
}

To ensure the PII and sensitive medical information stays secure, create a JSON schema that configures those fields for automatic encryption. 为了确保PII和敏感医疗信息的安全,请创建一个JSON模式,配置这些字段进行自动加密。For example:例如:

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
bsonType: "int"
},
{
path: "patientInfo.ssn",
bsonType: "string"
},
{
path: "medications",
bsonType: "array"
},
{
path: "patientInfo.billing",
bsonType: "object"
}
]
}

MongoDB creates encryption keys for each field automatically. Configure AutoEncryptionSettings on the client, then use the createEncryptedCollection helper method to create your collections.MongoDB会自动为每个字段创建加密键。在客户端上配置AutoEncryptionSettings,然后使用createEncryptedCollection帮助程序方法创建集合。

If you are using explicit encryption, you must create a unique Data Encryption Key for each encrypted field in advance. Add a keyId field to each entry that includes the key:如果使用显式加密,则必须提前为每个加密字段创建一个唯一的数据加密键。向包含键的每个条目添加一个keyId字段:

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
keyId: "<unique data encryption key>",
bsonType: "int"
},
{
path: "patientInfo.ssn",
keyId: "<unique data encryption key>",
bsonType: "string"
},
. . .
]
}

Configure Fields for Querying配置查询字段

Include the queries property on fields you want to make queryable in your JSON schema. 在JSON模式中,在要使其可查询的字段上包含queries属性。This enables an authorized client to issue read and write queries against those fields. 这使授权的客户端能够针对这些字段发出读写查询。If you omit the queries property, you prevent clients from querying a field.如果省略了queries属性,则会阻止客户端查询字段。

Example实例

Add the queries property to the previous example schema to make the patientId and patientInfo.ssn fields queryable.queries属性添加到上一个示例架构中,使patientIdpatientInfo.ssn字段可查询。

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
bsonType: "int",
queries: { queryType: "equality" }
},
{
path: "patientInfo.ssn",
bsonType: "string",
queries: { queryType: "equality" }
},
{
path: "medications",
bsonType: "array"
},
{
path: "patientInfo.billing",
bsonType: "object"
},
]
}

Configure Contention Factor配置争用系数

Include the contention property on queryable fields to prefer either find performance, or write and update performance.在可查询字段中包含contention属性,以便查找性能或写入和更新性能。

Inserting the same field/value pair into multiple documents in close succession can cause conflicts that delay insert operations.将同一字段/值对连续插入多个文档可能会导致冲突,从而延迟插入操作。

MongoDB tracks the occurrences of each field/value pair in an encrypted collection using an internal counter. MongoDB使用内部计数器跟踪加密集合中每个字段/值对的出现情况。The contention factor partitions this counter, similar to an array. 争用因子对该计数器进行分区,类似于数组。This minimizes issues with incrementing the counter when using insert, update, or findAndModify to add or modify an encrypted field with the same field/value pair in close succession. 当使用insertupdatefindAndModify来连续添加或修改具有相同字段/值对的加密字段时,这可以最大限度地减少计数器递增的问题。contention = 0 creates an array with one element at index 0. 创建一个在索引0处有一个元素的数组。contention = 4 creates an array with 5 elements at indexes 0-4. MongoDB increments a random array element during insert. 创建一个在索引0-4处具有5个元素的数组。MongoDB在插入过程中增加一个随机数组元素。If unset, contention defaults to 8.如果未设置,contention默认为8。

High contention improves the performance of insert and update operations on low cardinality fields, but decreases find performance.高争用提高了对低基数字段的插入和更新操作的性能,但降低了查找性能。

Consider increasing contention above the default value of 8 only if:只有在以下情况下,才考虑将争用contention到默认值8以上:

  • The field has low cardinality or low selectivity. 该字段具有低基数或低选择性。A state field may have 50 values, but if 99% of the data points use {state: NY}, that pair is likely to cause contention.一个state字段可能有50个值,但如果99%的数据点使用{state: NY},则该对可能会引起争用。
  • Write and update operations frequently modify the field. 写入和更新操作经常修改字段。Since high contention values sacrifice find performance in favor of write and update operations, the benefit of a high contention factor for a rarely updated field is unlikely to outweigh the drawback.由于高争用值牺牲了查找性能而有利于写入和更新操作,因此对于很少更新的字段,高争用因子的好处不太可能超过缺点。

Consider decreasing contention if:如果出现以下情况,请考虑减少contention

  • The field is high cardinality and contains entirely unique values, such as a credit card number.该字段具有很高的基数,并且包含完全唯一的值,例如信用卡号。
  • The field is often queried, but never or rarely updated. In this case, find performance is preferable to write and update performance.该字段经常被查询,但从未更新或很少更新。在这种情况下,查找性能优于写入和更新性能。

Example实例

The example below sets contention to 0 for the low cardinality Social Security Number (SSN) and patient ID fields, since these are unique identifiers that shouldn't repeat in the data set:以下示例将低基数社会保障号(SSN)和患者ID字段的contention设置为0,因为这些是不应在数据集中重复的唯一标识符:

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
bsonType: "int",
queries: { queryType: "equality",
contention: "0"}
},
{
path: "patientInfo.ssn",
bsonType: "string",
queries: { queryType: "equality",
contention: "0"}
},
...
]
}

Query Types查询类型

Passing a query type to the queries option in your encrypted fields object sets the allowed query types for the field. 将查询类型传递给加密字段对象中的queries选项将设置字段允许的查询类型。Querying non-encrypted fields or encrypted fields with a supported query type returns encrypted data that is then decrypted at the client.使用支持的查询类型查询非加密字段或加密字段会返回加密数据,然后在客户端对其进行解密。

Queryable Encryption currently supports none and equality query types. If the query type is unspecified, it defaults to none. 可查询加密当前支持none查询类型和equality查询类型。如果未指定查询类型,则默认为“无”。If the query type is none, the field is encrypted, but clients can't query it.如果查询类型为none,则字段是加密的,但客户端无法查询它。

The equality query type supports the following expressions:equality查询类型支持以下表达式:

Note

Queries that compare an encrypted field to null or to a regular expression result in an error, even with supported query operators.即使使用支持的查询运算符,将加密字段与null或正则表达式进行比较的查询也会导致错误。

Queryable Encryption equality queries don't support read or write operations on a field when the operation compares the encrypted field to any of the following BSON types:当操作将加密字段与以下任何BSON类型进行比较时,可查询加密equality(相等)查询不支持对字段进行读取或写入操作:

  • double
  • decimal128
  • object
  • array
  • javascriptWithScope (Deprecated in MongoDB 4.4)

Client and Server Schemas客户端和服务器架构

MongoDB supports using schema validation to enforce encryption of specific fields in a collection. MongoDB支持使用模式验证来强制加密集合中的特定字段。Clients using automatic Queryable Encryption have specific behavior depending on the database connection configuration:根据数据库连接配置,使用自动可查询加密的客户端具有特定行为:

  • If the connection encryptedFieldsMap object contains a key for the specified collection, the client uses that object to perform automatic Queryable Encryption, rather than using the remote schema. At a minimum, the local rules must encrypt those fields that the remote schema marks as requiring encryption.如果连接encryptedFieldsMap对象包含指定集合的键,则客户端将使用该对象执行自动可查询加密,而不是使用远程架构。至少,本地规则必须对远程架构标记为需要加密的字段进行加密。
  • If the connection encryptedFieldsMap object does not contain a key for the specified collection, the client downloads the server-side remote schema for the collection and uses it to perform automatic Queryable Encryption.如果连接encryptedFieldsMap对象不包含指定集合的键,则客户端将下载该集合的服务器端远程架构,并使用它执行自动可查询加密。

    Important

    Behavior Considerations行为注意事项

    When a client does not have an encryption schema for the specified collection, the following occurs:当客户端没有指定集合的加密架构时,会发生以下情况:

    • The client trusts that the server has a valid schema with respect to automatic Queryable Encryption.客户端信任服务器具有关于自动可查询加密的有效架构。
    • The client uses the remote schema to perform automatic Queryable Encryption only. The client does not enforce any other validation rules specified in the schema.客户端使用远程架构仅执行自动可查询加密。客户端不强制执行架构中指定的任何其他验证规则。

To learn more about automatic Queryable Encryption, see the following resources:要了解有关自动可查询加密的更多信息,请参阅以下资源:

Enable Queryable Encryption启用可查询加密

Enable Queryable Encryption before creating a collection. Enabling Queryable Encryption after creating a collection does not encrypt fields on documents already in that collection. You can enable Queryable Encryption on fields in a JSON schema in one of two ways:在创建集合之前启用可查询加密。在创建集合后启用可查询加密不会加密该集合中已存在的文档上的字段。您可以通过以下两种方式之一对JSON模式中的字段启用Queryable Encryption:

  • Pass the JSON schema, represented by the encryptedFieldsObject constant, to the client that the application uses to create the collection:将由encryptedFieldsObject常量表示的JSON架构传递给应用程序用于创建集合的客户端:
const client = new MongoClient(uri, {
autoEncryption: {
keyVaultNameSpace: "<your keyvault namespace>",
kmsProviders: "<your kms provider>",
extraOptions: {
cryptSharedLibPath: "<path to FLE Shared Library>"
},
encryptedFieldsMap: {
"<databaseName.collectionName>": { encryptedFieldsObject }
}
}

...

await client.db("<database name>").createCollection("<collection name>");
}

For more information on autoEncryption configuration options, see the section on MongoClient Options for Queryable Encryption.有关autoEncryption配置选项的更多信息,请参阅MongoClient可查询加密选项一节。

  • Pass the encrypted fields object to createCollection() to create a new collection:将加密字段对象传递给createCollection()以创建新集合:
await encryptedDB.createCollection("<collection name>", {
encryptedFields: encryptedFieldsObject
});
Tip

Specify the encrypted fields when you create the collection, and also when you create a client to access the collection. 在创建集合时以及在创建访问集合的客户端时指定加密字段。This ensures that if the server's security is compromised, the information is still encrypted through the client.这样可以确保,如果服务器的安全性受到威胁,信息仍然通过客户端加密。

Important

Explicitly create your collection, rather than creating it implicitly with an insert operation. When you create a collection using createCollection(), MongoDB creates an index on the encrypted fields. Without this index, queries on encrypted fields may run slowly.显式创建集合,而不是使用插入操作隐式创建集合。当您使用createCollection()创建集合时,MongoDB会在加密字段上创建一个索引。如果没有此索引,对加密字段的查询可能会运行缓慢。