properties) {
+			return new EncryptedFieldsOptions(null, List.copyOf(properties));
+		}
+
+		/**
+		 * Add a new {@link QueryableJsonSchemaProperty queryable property} for the given source property.
+		 * 
+		 * Please note that, a given {@link JsonSchemaProperty} may override options from a given {@link MongoJsonSchema} if
+		 * set.
+		 *
+		 * @param property the queryable source - typically
+		 *          {@link org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.EncryptedJsonSchemaProperty
+		 *          encrypted}.
+		 * @param characteristics the query options to set.
+		 * @return new instance of {@link EncryptedFieldsOptions}.
+		 */
+		@Contract("_, _ -> new")
+		@CheckReturnValue
+		public EncryptedFieldsOptions queryable(JsonSchemaProperty property, QueryCharacteristic... characteristics) {
+
+			List targetPropertyList = new ArrayList<>(queryableProperties.size() + 1);
+			targetPropertyList.addAll(queryableProperties);
+			targetPropertyList.add(JsonSchemaProperty.queryable(property, List.of(characteristics)));
+
+			return new EncryptedFieldsOptions(schema, targetPropertyList);
+		}
+
+		public Document toDocument() {
+			return new Document("fields", selectPaths());
+		}
+
+		private List selectPaths() {
+
+			Map fields = new LinkedHashMap<>();
+			for (Document field : fromSchema()) {
+				fields.put(field.get("path", String.class), field);
+			}
+			for (Document field : fromProperties()) {
+				fields.put(field.get("path", String.class), field);
+			}
+			return List.copyOf(fields.values());
+		}
+
+		private List fromProperties() {
+
+			if (queryableProperties.isEmpty()) {
+				return List.of();
+			}
+
+			List converted = new ArrayList<>(queryableProperties.size());
+			for (QueryableJsonSchemaProperty property : queryableProperties) {
+
+				Document field = new Document("path", property.getIdentifier());
+
+				if (!property.getTypes().isEmpty()) {
+					field.append("bsonType", property.getTypes().iterator().next().toBsonType().value());
+				}
+
+				if (property
+						.getTargetProperty() instanceof IdentifiableJsonSchemaProperty.EncryptedJsonSchemaProperty encrypted) {
+					if (encrypted.getKeyId() != null) {
+						if (encrypted.getKeyId() instanceof String stringKey) {
+							field.append("keyId",
+									new BsonBinary(BsonBinarySubType.UUID_STANDARD, stringKey.getBytes(StandardCharsets.UTF_8)));
+						} else {
+							field.append("keyId", encrypted.getKeyId());
+						}
+					}
+				}
+
+				field.append("queries", StreamSupport.stream(property.getCharacteristics().spliterator(), false)
+						.map(QueryCharacteristic::toDocument).toList());
+
+				if (!field.containsKey("keyId")) {
+					field.append("keyId", BsonNull.VALUE);
+				}
+
+				converted.add(field);
+			}
+			return converted;
+		}
+
+		private List fromSchema() {
+
+			if (schema == null) {
+				return List.of();
+			}
+
+			Document root = schema.schemaDocument();
+			Map paths = new LinkedHashMap<>();
+			collectPaths(root, null, paths);
+
+			List fields = new ArrayList<>();
+			if (!paths.isEmpty()) {
+
+				for (Entry entry : paths.entrySet()) {
+					Document field = new Document("path", entry.getKey());
+					field.append("keyId", entry.getValue().getOrDefault("keyId", BsonNull.VALUE));
+					if (entry.getValue().containsKey("bsonType")) {
+						field.append("bsonType", entry.getValue().get("bsonType"));
+					}
+					field.put("queries", entry.getValue().get("queries"));
+					fields.add(field);
+				}
+			}
+
+			return fields;
+		}
+	}
+
+	private static void collectPaths(Document document, @Nullable String currentPath, Map paths) {
+
+		if (document.containsKey("type") && document.get("type").equals("object")) {
+			Object o = document.get("properties");
+			if (o == null) {
+				return;
+			}
+
+			if (o instanceof Document properties) {
+				for (Entry entry : properties.entrySet()) {
+					if (entry.getValue() instanceof Document nested) {
+
+						String path = currentPath == null ? entry.getKey() : (currentPath + "." + entry.getKey());
+						if (nested.containsKey("encrypt")) {
+							Document target = new Document(nested.get("encrypt", Document.class));
+							if (nested.containsKey("queries")) {
+								List> queries = nested.get("queries", List.class);
+								if (!queries.isEmpty() && queries.iterator().next() instanceof Document qd) {
+									target.putAll(qd);
+								}
+							}
+							paths.put(path, target);
+						} else {
+							collectPaths(nested, path, paths);
+						}
+					}
+				}
+			}
+		}
+	}
+
 	/**
 	 * Encapsulation of options applied to define collections change stream behaviour.
 	 *
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java
index f64391e8cd..601b6898b8 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java
@@ -19,11 +19,13 @@
  * Encryption algorithms supported by MongoDB Client Side Field Level Encryption.
  *
  * @author Christoph Strobl
+ * @author Ross Lawley
  * @since 3.3
  */
 public final class EncryptionAlgorithms {
 
 	public static final String AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic";
 	public static final String AEAD_AES_256_CBC_HMAC_SHA_512_Random = "AEAD_AES_256_CBC_HMAC_SHA_512-Random";
+	public static final String RANGE = "Range";
 
 }
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java
index 65a5131dd1..38269787cb 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java
@@ -22,6 +22,7 @@
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
 
 import org.bson.BsonNull;
 import org.bson.Document;
@@ -39,6 +40,7 @@
 import org.springframework.data.mapping.PropertyPath;
 import org.springframework.data.mapping.context.MappingContext;
 import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
+import org.springframework.data.mongodb.core.CollectionOptions.EncryptedFieldsOptions;
 import org.springframework.data.mongodb.core.CollectionOptions.TimeSeriesOptions;
 import org.springframework.data.mongodb.core.convert.MongoConverter;
 import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper;
@@ -83,6 +85,7 @@
  * @author Mark Paluch
  * @author Christoph Strobl
  * @author Ben Foster
+ * @author Ross Lawley
  * @since 2.1
  * @see MongoTemplate
  * @see ReactiveMongoTemplate
@@ -375,8 +378,15 @@ public CreateCollectionOptions convertToCreateCollectionOptions(@Nullable Collec
 			result.timeSeriesOptions(options);
 		});
 
-		collectionOptions.getChangeStreamOptions().ifPresent(it -> result
-				.changeStreamPreAndPostImagesOptions(new ChangeStreamPreAndPostImagesOptions(it.getPreAndPostImages())));
+		collectionOptions.getChangeStreamOptions() //
+				.map(CollectionOptions.CollectionChangeStreamOptions::getPreAndPostImages) //
+				.map(ChangeStreamPreAndPostImagesOptions::new) //
+				.ifPresent(result::changeStreamPreAndPostImagesOptions);
+
+		collectionOptions.getEncryptedFieldsOptions() //
+				.map(EncryptedFieldsOptions::toDocument) //
+				.filter(Predicate.not(Document::isEmpty)) //
+				.ifPresent(result::encryptedFields);
 
 		return result;
 	}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityResultConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityResultConverter.java
new file mode 100644
index 0000000000..c04ae9d603
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityResultConverter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.core;
+
+import org.bson.Document;
+
+enum EntityResultConverter implements QueryResultConverter