Skip to content

DRIVERS-3213 add text search explicit encryption API and tests #1824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 66 additions & 8 deletions source/client-side-encryption/client-side-encryption.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ QEv1 and QEv2 are incompatible.
MongoDB 8.0 dropped `queryType=rangePreview` and added `queryType=range`
([SPM-3583](https://jira.mongodb.org/browse/SPM-3583)).

MongoDB 8.2 added unstable support for QE text queries ([SPM-2880](https://jira.mongodb.org/browse/SPM-2880))

## META

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
Expand Down Expand Up @@ -1256,6 +1258,7 @@ class EncryptOpts {
contentionFactor: Optional<Int64>,
queryType: Optional<String>
rangeOpts: Optional<RangeOpts>
textOpts: Optional<TextOpts>
}

// RangeOpts specifies index options for a Queryable Encryption field supporting "range" queries.
Expand All @@ -1273,6 +1276,48 @@ class RangeOpts {
// precision determines the number of significant digits after the decimal point. May only be set for double or decimal128.
precision: Optional<Int32>
}

// TextOpts specifies options for a Queryable Encryption field supporting text queries.
// NOTE: TextOpts is currently unstable API and subject to backwards breaking changes.
class TextOpts {
// substring contains further options to support substring queries.
substring: Optional<SubstringOpts>,
// prefix contains further options to support prefix queries.
prefix: Optional<PrefixOpts>,
// suffix contains further options to support suffix queries.
suffix: Optional<SuffixOpts>,
// caseSensitive determines whether text indexes for this field are case sensitive.
caseSensitive: bool,
// diacriticSensitive determines whether text indexes for this field are diacritic sensitive.
diacriticSensitive: bool
}

// NOTE: SubstringOpts is currently unstable API and subject to backwards breaking changes.
class SubstringOpts {
// strMaxLength is the maximum allowed length to insert. Inserting longer strings will error.
strMaxLength: Int32,
// strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
strMinQueryLength: Int32,
// strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
strMaxQueryLength: Int32,
}

// NOTE: PrefixOpts is currently unstable API and subject to backwards breaking changes.
class PrefixOpts {
// strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
strMinQueryLength: Int32,
// strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
strMaxQueryLength: Int32,
}

// NOTE: SuffixOpts is currently unstable API and subject to backwards breaking changes.
class SuffixOpts {
// strMinQueryLength is the minimum allowed query length. Querying with a shorter string will error.
strMinQueryLength: Int32,
// strMaxQueryLength is the maximum allowed query length. Querying with a longer string will error.
strMaxQueryLength: Int32,
}

```

Explicit encryption requires a key and algorithm. Keys are either identified by `_id` or by alternate name. Exactly one
Expand All @@ -1295,34 +1340,45 @@ One of the strings:
- "Indexed"
- "Unindexed"
- "Range"
- "TextPreview"

The result of explicit encryption with the "Indexed" or "Range" algorithm must be processed by the server to insert or
query. Drivers MUST document the following behavior:
The result of explicit encryption with the "Indexed", "Range", or "TextPreview" algorithm must be processed by the
server to insert or query. Drivers MUST document the following behavior:

> To insert or query with an "Indexed" or "Range" encrypted payload, use a `MongoClient` configured with
> To insert or query with an "Indexed", "Range", or "TextPreview" encrypted payload, use a `MongoClient` configured with
> `AutoEncryptionOpts`. `AutoEncryptionOpts.bypassQueryAnalysis` may be true. `AutoEncryptionOpts.bypassAutoEncryption`
> must be false.
> must be false. The "TextPreview" algorithm is in preview and should be used for experimental workloads only. These
> features are unstable and their security is not guaranteed until released as Generally Available (GA). The GA version
> of these features may not be backwards compatible with the preview version.

#### contentionFactor

contentionFactor may be used to tune performance. Only applies when algorithm is "Indexed" or "Range". libmongocrypt
returns an error if contentionFactor is set for a non-applicable algorithm.
contentionFactor may be used to tune performance. Only applies when algorithm is "Indexed", "Range", or "TextPreview".
libmongocrypt returns an error if contentionFactor is set for a non-applicable algorithm.

#### queryType

One of the strings:

- "equality"
- "range"
- "prefixPreview"
- "suffixPreview"
- "substringPreview"

queryType only applies when algorithm is "Indexed" or "Range". libmongocrypt returns an error if queryType is set for a
non-applicable queryType.
queryType only applies when algorithm is "Indexed", "Range", or "TextPreview". libmongocrypt returns an error if
queryType is set for a non-applicable algorithm.

#### rangeOpts

rangeOpts only applies when algorithm is "Range". libmongocrypt returns an error if rangeOpts is set for a
non-applicable algorithm.

#### textOpts

textOpts only applies when algorithm is "TextPreview". libmongocrypt returns an error if textOpts is set for a
non-applicable algorithm.

## User facing API: When Auto Encryption Fails

Auto encryption requires parsing the MongoDB query language client side (with the [mongocryptd](#mongocryptd) process or
Expand Down Expand Up @@ -2463,6 +2519,8 @@ explicit session parameter as described in the [Drivers Sessions Specification](

## Changelog

- 2025-08-06: Add `TextPreview` algorithm.

- 2024-02-19: Add custom options AWS credential provider.

- 2024-10-09: Add retry prose test.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"fields": [
{
"keyId": {
"$binary": {
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "prefixPreview",
"strMinQueryLength": {
"$numberInt": "2"
},
"strMaxQueryLength": {
"$numberInt": "10"
},
"caseSensitive": true,
"diacriticSensitive": true
},
{
"queryType": "suffixPreview",
"strMinQueryLength": {
"$numberInt": "2"
},
"strMaxQueryLength": {
"$numberInt": "10"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"fields": [
{
"keyId": {
"$binary": {
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "substringPreview",
"strMaxLength": {
"$numberInt": "10"
},
"strMinQueryLength": {
"$numberInt": "2"
},
"strMaxQueryLength": {
"$numberInt": "10"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
Loading
Loading