Create an Encrypted Collection and Insert Documents
On this page
Overview
This guide shows you how to create a Queryable Encryption-enabled collection and insert a document with encrypted fields.
After you complete the steps in this guide, you should be able to create an encrypted collection and insert a document with fields that are encrypted with your Customer Master Key.
Before You Start
Create your Queryable Encryption-enabled application before creating an encrypted collection.
If you are using explicit encryption, you must also create a unique Data Encryption Key for each encrypted field in advance. For more information, see Encryption Keys and Key Vaults.
Procedure
Specify Fields to Encrypt
To encrypt a field, add it to the encryption schema. To enable
queries on a field, add the queries
property. You can enable fields to
be queryable by either equality queries or range queries. The following
steps demonstrate how to specify fields to encrypt with each query type.
Specify Fields for Equality Queries
To enable equality queries on a field, add the field to the encryption schema with a
queryType
of"equality"
. The following code sample encrypts both thessn
andbilling
fields, but only thessn
field is queryable:const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, ], }, }; var encryptedFields = new BsonDocument { { "fields", new BsonArray { new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.ssn" }, { "bsonType", "string" }, { "queries", new BsonDocument("queryType", "equality") } }, new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.billing" }, { "bsonType", "object" } } } } }; encryptedFieldsMap := bson.M{ "fields": []bson.M{ bson.M{ "keyId": nil, "path": "patientRecord.ssn", "bsonType": "string", "queries": []bson.M{ { "queryType": "equality", }, }, }, bson.M{ "keyId": nil, "path": "patientRecord.billing", "bsonType": "object", }, }, } BsonDocument encryptedFieldsMap = new BsonDocument().append("fields", new BsonArray(Arrays.asList( new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.ssn")) .append("bsonType", new BsonString("string")) .append("queries", new BsonDocument() .append("queryType", new BsonString("equality"))), new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.billing")) .append("bsonType", new BsonString("object"))))); const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, ], }, }; encrypted_fields_map = { "fields": [ { "path": "patientRecord.ssn", "bsonType": "string", "queries": [{"queryType": "equality"}] }, { "path": "patientRecord.billing", "bsonType": "object", } ] } Specify Fields for Range Queries
To enable range queries on a field, add the field to the encryption schema with a
queryType
of"range"
. The following example adds thebillAmount
field to the encryption schema created in the preceding step and enables range queries on it:const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, { path: "patientRecord.billAmount", bsonType: "int", queries: { queryType: "range", sparsity: 1, trimFactor: 4, min: 100, max: 2000, }, }, ], }, }; var encryptedFields = new BsonDocument { { "fields", new BsonArray { new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.ssn" }, { "bsonType", "string" }, { "queries", new BsonDocument("queryType", "equality") } }, new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.billing" }, { "bsonType", "object" } }, new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.billAmount" }, { "bsonType", "int" }, { "queries", new BsonDocument { { "queryType", "range" }, { "sparsity", 1 }, { "min", 100 }, { "max", 2000 }, { "trimFactor", 4 } } }, } } } }; encryptedFieldsMap := bson.M{ "fields": []bson.M{ bson.M{ "keyId": nil, "path": "patientRecord.ssn", "bsonType": "string", "queries": []bson.M{ { "queryType": "equality", }, }, }, bson.M{ "keyId": nil, "path": "patientRecord.billing", "bsonType": "object", }, bson.M{ "keyId": nil, "path": "patientRecord.billAmount", "bsonType": "int", "queries": []bson.M{ { "queryType": "range", "sparsity": 1, "min": 100, "max": 2000, "trimFactor": 4, }, }, }, }, } BsonDocument encryptedFieldsMap = new BsonDocument().append("fields", new BsonArray(Arrays.asList( new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.ssn")) .append("bsonType", new BsonString("string")) .append("queries", new BsonDocument() .append("queryType", new BsonString("equality"))), new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.billing")) .append("bsonType", new BsonString("object")), new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.billAmount")) .append("bsonType", new BsonString("int")) .append("queries", new BsonDocument() .append("queryType", new BsonString("range")) .append("sparsity", new BsonInt32(1)) .append("trimFactor", new BsonInt32(4)) .append("min", new BsonInt32(100)) .append("max", new BsonInt32(2000)) )))); const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, { path: "patientRecord.billAmount", bsonType: "int", queries: { queryType: "range", sparsity: 1, trimFactor: 4, min: 100, max: 2000, }, }, ], }, }; encrypted_fields_map = { "fields": [ { "path": "patientRecord.ssn", "bsonType": "string", "queries": [{"queryType": "equality"}] }, { "path": "patientRecord.billing", "bsonType": "object", }, { "path": "patientRecord.billAmount", "bsonType": "int", "queries": [{ "queryType": "range", "sparsity": 1, "min": 100, "max": 2000, "trimFactor": 4 }], }, ] }
For extended versions of these steps, see Create an Encryption Schema.
Instantiate ClientEncryption
to access the API for the encryption helper methods
const clientEncryption = encryptedClient.getClientEncryption();
var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviderCredentials ); var clientEncryption = new ClientEncryption(clientEncryptionOptions);
opts := options.ClientEncryption(). SetKeyVaultNamespace(keyVaultNamespace). SetKmsProviders(kmsProviderCredentials) clientEncryption, err := mongo.NewClientEncryption(encryptedClient, opts) if err != nil { panic(fmt.Sprintf("Unable to create a ClientEncryption instance due to the following error: %s\n", err)) }
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(uri)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviderCredentials) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const clientEncryption = new ClientEncryption( encryptedClient, autoEncryptionOptions );
client_encryption = ClientEncryption( kms_providers=kms_provider_credentials, key_vault_namespace=key_vault_namespace, key_vault_client=encrypted_client, codec_options=CodecOptions(uuid_representation=STANDARD) )
Create the collection
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.
Create your encrypted collection by using the encryption
helper method accessed through the ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
await clientEncryption.createEncryptedCollection( encryptedDatabaseName, encryptedCollectionName, { provider: kmsProviderName, createCollectionOptions: encryptedFieldsMap, masterKey: customerMasterKeyCredentials, } );
The C# version of this tutorial uses separate classes as data models
to represent the document structure.
Add the following Patient
, PatientRecord
, and PatientBilling
classes to your project:
using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; [ ]public class Patient { public ObjectId Id { get; set; } public string PatientName { get; set; } public PatientRecord PatientRecord { get; set; } }
public class PatientRecord { public string Ssn { get; set; } public PatientBilling Billing { get; set; } public int BillAmount { get; set; } }
public class PatientBilling { public string CardType { get; set; } public long CardNumber { get; set; } }
After you've added these classes, create your encrypted collection by
using the encryption helper method accessed through the
ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
var createCollectionOptions = new CreateCollectionOptions<Patient> { EncryptedFields = encryptedFields }; clientEncryption.CreateEncryptedCollection(patientDatabase, encryptedCollectionName, createCollectionOptions, kmsProviderName, customerMasterKeyCredentials);
Tip
Database vs. Database Name
The method that creates the collection requires a reference to a database object rather than the database name.
The Golang version of this tutorial uses data models to represent the document structure. Add the following structs to your project to represent the data in your collection:
type PatientDocument struct { PatientName string `bson:"patientName"` PatientID int32 `bson:"patientId"` PatientRecord PatientRecord `bson:"patientRecord"` }
type PatientRecord struct { SSN string `bson:"ssn"` Billing PaymentInfo `bson:"billing"` BillAmount int `bson:"billAmount"` }
type PaymentInfo struct { Type string `bson:"type"` Number string `bson:"number"` }
After you've added these classes, create your encrypted
collection by using the encryption helper method accessed
through the ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
createCollectionOptions := options.CreateCollection().SetEncryptedFields(encryptedFieldsMap) _, _, err = clientEncryption.CreateEncryptedCollection( context.TODO(), encryptedClient.Database(encryptedDatabaseName), encryptedCollectionName, createCollectionOptions, kmsProviderName, customerMasterKey, )
Tip
Database vs. Database Name
The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.
Create your encrypted collection by using the encryption
helper method accessed through the ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
CreateCollectionOptions createCollectionOptions = new CreateCollectionOptions().encryptedFields(encryptedFieldsMap); CreateEncryptedCollectionParams encryptedCollectionParams = new CreateEncryptedCollectionParams(kmsProviderName); encryptedCollectionParams.masterKey(customerMasterKeyCredentials); try { clientEncryption.createEncryptedCollection( encryptedClient.getDatabase(encryptedDatabaseName), encryptedCollectionName, createCollectionOptions, encryptedCollectionParams); }
Tip
Database vs. Database Name
The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.
Note
Import ClientEncryption
When using the Node.js driver v6.0 and later, you must import
ClientEncryption
from mongodb
.
For earlier driver versions, import ClientEncryption
from
mongodb-client-encryption
.
Create your encrypted collection by using the encryption
helper method accessed through the ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
await clientEncryption.createEncryptedCollection( encryptedDatabase, encryptedCollectionName, { provider: kmsProviderName, createCollectionOptions: encryptedFieldsMap, masterKey: customerMasterKeyCredentials, } );
Tip
Database vs. Database Name
The method that creates the encrypted collection requires a reference to a database object rather than the database name.
Create your encrypted collection by using the encryption
helper method accessed through the ClientEncryption
class.
This method automatically generates data encryption keys for your
encrypted fields and creates the encrypted collection:
client_encryption.create_encrypted_collection( encrypted_client[encrypted_database_name], encrypted_collection_name, encrypted_fields_map, kms_provider_name, customer_master_key_credentials, )
Tip
Database vs. Database Name
The method that creates the encrypted collection requires a reference to a database object rather than the database name. You can obtain this reference by using a method on your client object.
For additional information, see Enable Queryable Encryption when Creating a Collection.
Insert a Document with Encrypted Fields
Create a sample document that describes a patient's personal information.
Use the encrypted client to insert it into the patients
collection,
as shown in the following example:
const patientDocument = { patientName: "Jon Doe", patientId: 12345678, patientRecord: { ssn: "987-65-4320", billing: { type: "Visa", number: "4111111111111111", }, billAmount: 1500, }, }; const encryptedCollection = encryptedClient .getDB(encryptedDatabaseName) .getCollection(encryptedCollectionName); const insertResult = await encryptedCollection.insertOne(patientDocument);
Create a sample document that describes a patient's personal information.
Use the encrypted client to insert it into the patients
collection,
as shown in the following example:
var patient = new Patient { PatientName = "Jon Doe", Id = new ObjectId(), PatientRecord = new PatientRecord { Ssn = "987-65-4320", Billing = new PatientBilling { CardType = "Visa", CardNumber = 4111111111111111, }, BillAmount = 1500 } }; var encryptedCollection = encryptedClient.GetDatabase(encryptedDatabaseName). GetCollection<Patient>(encryptedCollectionName); encryptedCollection.InsertOne(patient);
Create a sample document that describes a patient's personal information.
Use the encrypted client to insert it into the patients
collection,
as shown in the following example:
patientDocument := &PatientDocument{ PatientName: "Jon Doe", PatientID: 12345678, PatientRecord: PatientRecord{ SSN: "987-65-4320", Billing: PaymentInfo{ Type: "Visa", Number: "4111111111111111", }, BillAmount: 1500, }, } coll := encryptedClient.Database(encryptedDatabaseName).Collection(encryptedCollectionName) _, err = coll.InsertOne(context.TODO(), patientDocument) if err != nil { panic(fmt.Sprintf("Unable to insert the patientDocument: %s", err)) }
This tutorial uses POJOs as data models to represent the document structure. To set up your application to use POJOs, add the following code:
CodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build(); CodecRegistry pojoCodecRegistry = fromRegistries(getDefaultCodecRegistry(), fromProviders(pojoCodecProvider));
To learn more about Java POJOs, see the Plain Old Java Object wikipedia article.
This tutorial uses the following POJOs:
Patient
PatientRecord
PatientBilling
You can view these classes in the models package of the complete Java application.
Add these POJO classes to your application. Then, create an instance
of a Patient
that describes a patient's personal information. Use
the encrypted client to insert it into the patients
collection,
as shown in the following example:
MongoDatabase encryptedDb = encryptedClient.getDatabase(encryptedDatabaseName).withCodecRegistry(pojoCodecRegistry); MongoCollection<Patient> collection = encryptedDb.getCollection(encryptedCollectionName, Patient.class); PatientBilling patientBilling = new PatientBilling("Visa", "4111111111111111"); PatientRecord patientRecord = new PatientRecord("987-65-4320", patientBilling, 1500); Patient patientDocument = new Patient("Jon Doe", patientRecord); InsertOneResult result = collection.insertOne(patientDocument);
Create a sample document that describes a patient's personal information.
Use the encrypted client to insert it into the patients
collection,
as shown in the following example:
const patientDocument = { patientName: "Jon Doe", patientId: 12345678, patientRecord: { ssn: "987-65-4320", billing: { type: "Visa", number: "4111111111111111", }, billAmount: 1500, }, }; const encryptedCollection = encryptedClient .db(encryptedDatabaseName) .collection(encryptedCollectionName); const result = await encryptedCollection.insertOne(patientDocument);
Create a sample document that describes a patient's personal information.
Use the encrypted client to insert it into the patients
collection,
as shown in the following example:
patient_document = { "patientName": "Jon Doe", "patientId": 12345678, "patientRecord": { "ssn": "987-65-4320", "billing": { "type": "Visa", "number": "4111111111111111", }, "billAmount": 1500, }, } encrypted_collection = encrypted_client[encrypted_database_name][encrypted_collection_name] result = encrypted_collection.insert_one(patient_document)
Next Steps
After creating a Queryable Encryption-enabled collection, you can query the encrypted fields.