Docs Menu
Docs Home
/
MongoDB Manual
/ / / / / /

Create an Encrypted Collection and Insert Documents

On this page

  • Overview
  • Before You Start
  • Procedure
  • Next Steps

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.

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.

1

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.

  1. 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 the ssn and billing fields, but only the ssn 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",
    }
    ]
    }
  2. 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 the billAmount 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.

2
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)
)
3

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;
[BsonIgnoreExtraElements]
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.

4

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)

After creating a Queryable Encryption-enabled collection, you can query the encrypted fields.

Back

Create & Query