From 7b274a5db300c294546b450f4a753ea2e8cb97c2 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Thu, 5 Mar 2026 10:53:16 +0000 Subject: [PATCH 1/5] CSHARP-5884: Support stored source in vector indexes Allows fields to be included or excluded. Does not allow `true` to be set because this will always fail for a vector index. --- ...eateAutoEmbeddingVectorSearchIndexModel.cs | 62 ++++++++++++- .../CreateVectorSearchIndexModel.cs | 66 +++++++++++++- .../CreateVectorSearchIndexModelBase.cs | 38 ++++++++ .../PipelineStageDefinitionBuilder.cs | 3 +- src/MongoDB.Driver/VectorSearchOptions.cs | 6 ++ .../Search/AtlasSearchIndexManagmentTests.cs | 86 ++++++++++++++----- .../Search/VectorSearchTests.cs | 3 +- 7 files changed, 237 insertions(+), 27 deletions(-) diff --git a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs index 40bc5d99a4a..e7017a55c4f 100644 --- a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs @@ -79,6 +79,62 @@ public CreateAutoEmbeddingVectorSearchIndexModel( { } + /// + /// Creates a new with the given fields + /// configured to be stored in the index. Note that storing full documents might significantly impact + /// performance during indexing and querying. Explicitly storing vector fields is not recommended. + /// + /// The fields to store. + /// A new model with the fields configured. + public CreateAutoEmbeddingVectorSearchIndexModel WithIncludedStoredFields( + params FieldDefinition[] includedStoredFields) + => new(Field, Name, AutoEmbeddingModelName, FilterFields.ToArray()) + { + IncludedStoredFields = includedStoredFields, + ExcludedStoredFields = null, + Modality = Modality, + }; + + /// + /// Creates a new with the given fields + /// configured to be stored in the index. Note that storing full documents might significantly impact + /// performance during indexing and querying. Explicitly storing vector fields is not recommended. + /// + /// The fields to store. + /// A new model with the fields configured. + public CreateAutoEmbeddingVectorSearchIndexModel WithIncludedStoredFields( + params Expression>[] includedStoredFields) + => WithIncludedStoredFields(includedStoredFields + .Select(f => (FieldDefinition)new ExpressionFieldDefinition(f)).ToArray()); + + /// + /// Creates a new with the given fields + /// configured to be excluded from being stored in the index. This is typically used to exclude vector fields + /// from being stored when other fields should be stored. + /// + /// The fields to exclude from being stored. + /// A new model with the fields configured. + public CreateAutoEmbeddingVectorSearchIndexModel WithExcludedStoredFields( + params FieldDefinition[] excludedStoredFields) + => new(Field, Name, AutoEmbeddingModelName, FilterFields.ToArray()) + { + ExcludedStoredFields = excludedStoredFields, + IncludedStoredFields = null, + Modality = Modality, + }; + + /// + /// Creates a new with the given fields + /// configured to be excluded from being stored in the index. This is typically used to exclude vector fields + /// from being stored when other fields should be stored. + /// + /// The fields to exclude from being stored. + /// A new model with the fields configured. + public CreateAutoEmbeddingVectorSearchIndexModel WithExcludedStoredFields( + params Expression>[] excludedStoredFields) + => WithExcludedStoredFields(excludedStoredFields + .Select(f => (FieldDefinition)new ExpressionFieldDefinition(f)).ToArray()); + /// internal override BsonDocument Render(RenderArgs renderArgs) { @@ -92,6 +148,10 @@ internal override BsonDocument Render(RenderArgs renderArgs) var fieldDocuments = new List { vectorField }; RenderFilterFields(renderArgs, fieldDocuments); - return new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; + + var indexDefinition = new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; + RenderStoredSource(renderArgs, indexDefinition); + + return indexDefinition; } } diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs index 5cf1234cc82..71c9ff7b0a2 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs @@ -101,6 +101,66 @@ public CreateVectorSearchIndexModel( { } + /// + /// Creates a new with the given fields configured + /// to be stored in the index. Note that storing full documents might significantly impact + /// performance during indexing and querying. Explicitly storing vector fields is not recommended. + /// + /// The fields to store. + /// A new model with the fields configured. + public CreateVectorSearchIndexModel WithIncludedStoredFields( + params FieldDefinition[] includedStoredFields) + => new(Field, Name, Similarity, Dimensions, FilterFields.ToArray()) + { + IncludedStoredFields = includedStoredFields, + ExcludedStoredFields = null, + Quantization = Quantization, + HnswMaxEdges = HnswMaxEdges, + HnswNumEdgeCandidates = HnswNumEdgeCandidates + }; + + /// + /// Creates a new with the given fields configured + /// to be stored in the index. Note that storing full documents might significantly impact + /// performance during indexing and querying. Explicitly storing vector fields is not recommended. + /// + /// The fields to store. + /// A new model with the fields configured. + public CreateVectorSearchIndexModel WithIncludedStoredFields( + params Expression>[] includedStoredFields) + => WithIncludedStoredFields(includedStoredFields + .Select(f => (FieldDefinition)new ExpressionFieldDefinition(f)).ToArray()); + + /// + /// Creates a new with the given fields configured + /// to be excluded from being stored in the index. This is typically used to exclude vector fields from being + /// stored when other fields should be stored. + /// + /// The fields to exclude from being stored. + /// A new model with the fields configured. + public CreateVectorSearchIndexModel WithExcludedStoredFields( + params FieldDefinition[] excludedStoredFields) + => new(Field, Name, Similarity, Dimensions, FilterFields.ToArray()) + { + ExcludedStoredFields = excludedStoredFields, + IncludedStoredFields = null, + Quantization = Quantization, + HnswMaxEdges = HnswMaxEdges, + HnswNumEdgeCandidates = HnswNumEdgeCandidates + }; + + /// + /// Creates a new with the given fields configured + /// to be excluded from being stored in the index. This is typically used to exclude vector fields from being + /// stored when other fields should be stored. + /// + /// The fields to exclude from being stored. + /// A new model with the fields configured. + public CreateVectorSearchIndexModel WithExcludedStoredFields( + params Expression>[] excludedStoredFields) + => WithExcludedStoredFields(excludedStoredFields + .Select(f => (FieldDefinition)new ExpressionFieldDefinition(f)).ToArray()); + /// internal override BsonDocument Render(RenderArgs renderArgs) { @@ -129,6 +189,10 @@ internal override BsonDocument Render(RenderArgs renderArgs) var fieldDocuments = new List { vectorField }; RenderFilterFields(renderArgs, fieldDocuments); - return new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; + + var indexDefinition = new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; + RenderStoredSource(renderArgs, indexDefinition); + + return indexDefinition; } } diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs index bed5b2c08fc..6c59b1a69c6 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs @@ -34,6 +34,22 @@ public abstract class CreateVectorSearchIndexModelBase : CreateSearch /// public IReadOnlyList> FilterFields { get; } + /// + /// The fields that must be stored in the index. Use + /// + /// or + /// to configure this. + /// + public IReadOnlyList> IncludedStoredFields { get; protected init; } + + /// + /// The fields that must NOT be stored in the index. Use + /// + /// or + /// to configure this. + /// + public IReadOnlyList> ExcludedStoredFields { get; protected init; } + /// /// Initializes a new instance of the class for a vector /// index where the vector embeddings are created manually. The required options for @@ -79,4 +95,26 @@ private protected void RenderFilterFields(RenderArgs renderArgs, List } } } + + /// + /// Called by subclasses to render the "storedSource" in the index definition. + /// + /// The render args. + /// The index document into which the stored source fields will go. + private protected void RenderStoredSource(RenderArgs renderArgs, BsonDocument indexDocument) + { + var exclude = ExcludedStoredFields?.Any() == true; + if (!exclude && IncludedStoredFields?.Any() != true) + { + return; + } + + var fields = new BsonArray(); + foreach (var field in exclude ? ExcludedStoredFields : IncludedStoredFields) + { + fields.Add(field.Render(renderArgs).FieldName); + } + + indexDocument.Add("storedSource", new BsonDocument { { exclude ? "exclude" : "include", fields } }); + } } diff --git a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs index bf7f6e6f61f..a49d06a610d 100644 --- a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs @@ -2175,7 +2175,8 @@ public static PipelineStageDefinition VectorSearch( { "numCandidates", options?.NumberOfCandidates ?? limit * 10, options?.Exact != true }, { "index", options?.IndexName ?? "default" }, { "filter", () => options?.Filter.Render(args with { RenderDollarForm = true }), options?.Filter != null }, - { "exact", true, options?.Exact == true } + { "exact", true, options?.Exact == true }, + { "returnStoredSource", true, options?.ReturnStoredSource == true }, }; if (queryVector.Vector is BsonString bsonString) diff --git a/src/MongoDB.Driver/VectorSearchOptions.cs b/src/MongoDB.Driver/VectorSearchOptions.cs index 84a58ab836e..341cfb7e445 100644 --- a/src/MongoDB.Driver/VectorSearchOptions.cs +++ b/src/MongoDB.Driver/VectorSearchOptions.cs @@ -46,5 +46,11 @@ public sealed class VectorSearchOptions /// The model to for auto-embedding in the query. Must be compatible with the model used to create the index. /// public string AutoEmbeddingModelName { get; set; } + + /// + /// Gets or sets a flag that specifies whether to perform a full document lookup on the backend database + /// or return only stored source fields directly from Atlas Search. + /// + public bool ReturnStoredSource { get; set; } } } diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs index 9d8994cc4dd..1a7aafbbd79 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs @@ -32,7 +32,7 @@ namespace MongoDB.Driver.Tests.Search public class AtlasSearchIndexManagementTests : LoggableTestClass { private const int Timeout = 5 * 60 * 1000; - private const int IndexesPollPeriod = 5000; + private const int IndexesPollPeriod = 10000; // Server polling is every 10 seconds private readonly IMongoCollection _collection; private readonly IMongoDatabase _database; @@ -101,7 +101,7 @@ public async Task Case2_driver_should_successfully_create_multiple_indexes_in_ba indexNamesActual.Should().BeEquivalentTo(indexDefinition1.Name, indexDefinition2.Name); - var indexes = await GetIndexes(async, indexDefinition1.Name, indexDefinition2.Name); + var indexes = await GetIndexes(async, expectTimeout: false, indexDefinition1.Name, indexDefinition2.Name); indexes[0]["latestDefinition"].AsBsonDocument.Should().Be(indexDefinitionBson); indexes[1]["latestDefinition"].AsBsonDocument.Should().Be(indexDefinitionBson); @@ -164,7 +164,7 @@ public async Task Case4_driver_can_update_a_search_index( _collection.SearchIndexes.Update(indexName, indexNewDefinition); } - var updatedIndex = await GetIndexes(async, indexName); + var updatedIndex = await GetIndexes(async, expectTimeout: false, indexName); updatedIndex[0]["latestDefinition"].AsBsonDocument.Should().Be(indexNewDefinition); } @@ -204,7 +204,7 @@ public async Task Case6_driver_can_create_and_list_search_indexes_with_non_defau indexNameCreated.Should().Be(indexName); - var indexes = await GetIndexes(async, indexName); + var indexes = await GetIndexes(async, expectTimeout: false, indexName); indexes[0]["latestDefinition"].AsBsonDocument.Should().Be(indexDefinitionBson); } @@ -235,7 +235,7 @@ public async Task Case7_driver_can_handle_search_index_types_when_creating_index : _collection.SearchIndexes.CreateOne(new CreateSearchIndexModel(indexName2, SearchIndexType.Search, _indexDefinition)); indexNameCreated.Should().Be(indexName2); - var indexCreated2 = await GetIndexes(async, indexName2); + var indexCreated2 = await GetIndexes(async, expectTimeout: false, indexName2); indexCreated2[0]["type"].AsString.Should().Be("search"); indexNameCreated = async @@ -243,7 +243,7 @@ public async Task Case7_driver_can_handle_search_index_types_when_creating_index : _collection.SearchIndexes.CreateOne(new CreateSearchIndexModel(indexName3, SearchIndexType.VectorSearch, _vectorIndexDefinition)); indexNameCreated.Should().Be(indexName3); - var indexCreated3 = await GetIndexes(async, indexName3); + var indexCreated3 = await GetIndexes(async, expectTimeout: false, indexName3); indexCreated3[0]["type"].AsString.Should().Be("vectorSearch"); } @@ -301,7 +301,7 @@ var indexDefinition createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("search"); var mappings = index["latestDefinition"].AsBsonDocument["mappings"].AsBsonDocument; @@ -333,7 +333,7 @@ public async Task Can_create_Atlas_vector_index_for_all_options_using_typed_API( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; @@ -365,7 +365,7 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; @@ -400,6 +400,8 @@ public async Task Can_create_Atlas_vector_index_for_all_options_with_filters( Quantization = VectorQuantization.Scalar, }; + indexModel = indexModel.WithIncludedStoredFields(e => e.SomeText, e => e.Filter3); + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); var createdName = async ? await collection.SearchIndexes.CreateOneAsync(indexModel) @@ -407,10 +409,11 @@ public async Task Can_create_Atlas_vector_index_for_all_options_with_filters( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"]; + var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -428,6 +431,12 @@ public async Task Can_create_Atlas_vector_index_for_all_options_with_filters( filterField["type"].AsString.Should().Be("filter"); filterField["path"].AsString.Should().Be($"Filter{i}"); } + + var storedSource = indexDefinition["storedSource"].AsBsonDocument; + var included = storedSource["include"].AsBsonArray; + included.Count.Should().Be(2); + included[0].AsString.Should().Be("Filter3"); + included[1].AsString.Should().Be("SomeText"); } [Theory(Timeout = Timeout)] @@ -444,6 +453,8 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f dimensions: 4, "f1", "f2", "f3"); + indexModel = indexModel.WithExcludedStoredFields("Floats", "SomeText"); + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); var createdName = async ? await collection.SearchIndexes.CreateOneAsync(indexModel) @@ -451,10 +462,11 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"]; + var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -472,6 +484,12 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f filterField["type"].AsString.Should().Be("filter"); filterField["path"].AsString.Should().Be($"f{i}"); } + + var storedSource = indexDefinition["storedSource"].AsBsonDocument; + var excluded = storedSource["exclude"].AsBsonArray; + excluded.Count.Should().Be(2); + excluded[0].AsString.Should().Be("Floats"); + excluded[1].AsString.Should().Be("SomeText"); } [Theory(Timeout = Timeout)] @@ -479,6 +497,7 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f public async Task Can_create_autoEmbed_vector_index_for_required_only_options( [Values(false, true)] bool async) { + // Note that these tests pass with Atlas local, but fail on the CI. SkipTests(); var indexName = "auto-embed-required" + (async ? "-async" : ""); @@ -492,7 +511,7 @@ public async Task Can_create_autoEmbed_vector_index_for_required_only_options( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; @@ -514,6 +533,7 @@ public async Task Can_create_autoEmbed_vector_index_for_required_only_options( public async Task Can_create_autoEmbed_vector_index_for_all_options( [Values(false, true)] bool async) { + // Note that these tests pass with Atlas local, but fail on the CI. SkipTests(); var indexName = "auto-embed-all" + (async ? "-async" : ""); @@ -531,7 +551,7 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; @@ -553,6 +573,7 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( [Values(false, true)] bool async) { + // Note that these tests pass with Atlas local, but fail on the CI. SkipTests(); var indexName = "auto-embed-filters-text" + (async ? "-async" : ""); @@ -563,6 +584,8 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( "voyage-4", "Filter1", "Filter2", "Filter3"); + indexModel = indexModel.WithExcludedStoredFields("Floats", "SomeText"); + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); var createdName = async ? await collection.SearchIndexes.CreateOneAsync(indexModel) @@ -570,10 +593,11 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"]; + var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -592,6 +616,12 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( indexField.Contains("quantization").Should().Be(false); indexField.Contains("hnswOptions").Should().Be(false); indexField.Contains("compression").Should().Be(false); + + var storedSource = indexDefinition["storedSource"].AsBsonDocument; + var excluded = storedSource["exclude"].AsBsonArray; + excluded.Count.Should().Be(2); + excluded[0].AsString.Should().Be("Floats"); + excluded[1].AsString.Should().Be("SomeText"); } [Theory(Timeout = Timeout)] @@ -599,6 +629,7 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( public async Task Can_create_autoEmbed_vector_index_with_filters_as_expressions( [Values(false, true)] bool async) { + // Note that these tests pass with Atlas local, but fail on the CI. SkipTests(); var indexName = "auto-embed-filters-expressions" + (async ? "-async" : ""); @@ -609,6 +640,8 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_expressions( "voyage-4", e => e.Filter1, e => e.Filter2, e => e.Filter3); + indexModel = indexModel.WithIncludedStoredFields(e => e.SomeText, e => e.Filter3); + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); var createdName = async ? await collection.SearchIndexes.CreateOneAsync(indexModel) @@ -616,10 +649,11 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_expressions( createdName.Should().Be(indexName); - var index = (await GetIndexes(async, indexName))[0]; + var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"]; + var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -638,6 +672,12 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_expressions( indexField.Contains("quantization").Should().Be(false); indexField.Contains("hnswOptions").Should().Be(false); indexField.Contains("compression").Should().Be(false); + + var storedSource = indexDefinition["storedSource"].AsBsonDocument; + var included = storedSource["include"].AsBsonArray; + included.Count.Should().Be(2); + included[0].AsString.Should().Be("Filter3"); + included[1].AsString.Should().Be("SomeText"); } private class EntityWithVector @@ -673,15 +713,14 @@ private async Task CreateIndexAndValidate(string indexName, BsonDo indexNameActual.Should().Be(indexName); - var result = await GetIndexes(async, indexName); + var result = await GetIndexes(async, expectTimeout: false, indexName); return result[0]; } - private async Task GetIndexes(bool async, params string[] indexNames) + private async Task GetIndexes(bool async, bool? expectTimeout = null, params string[] indexNames) { BsonDocument[] indexesFiltered = null!; var timeoutCount = 2; - bool? expectTimeout = null; while (expectTimeout != true || --timeoutCount >= 0) { List indexes; @@ -726,6 +765,7 @@ private static T TryGetValue(BsonDocument document, string name) return (T)result; } - private void SkipTests() => throw new SkipException("Test skipped because of CSHARP-5840."); + private void SkipTests() => throw new SkipException( + "Test skipped because they currently only work against Atlas Local or Community. See CSHARP-5840."); } } diff --git a/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs index 350c2b28359..a912c49b97a 100644 --- a/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs @@ -82,7 +82,8 @@ public void VectorSearch() var options = new VectorSearchOptions() { Filter = Builders.Filter.Gt("runtime", 1) & Builders.Filter.Gt("year", 1900), - IndexName = "sample_mflix__embedded_movies" + IndexName = "sample_mflix__embedded_movies", + ReturnStoredSource = true }; var results = GetEmbeddedMoviesCollection() From e978cea5f9eb415c37dcd2ab9cf3579c22d5d7d9 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Thu, 5 Mar 2026 12:47:53 +0000 Subject: [PATCH 2/5] CSHARP-5884: Add new fields for Auto embedding in Atlas Vector search indexes --- ...eateAutoEmbeddingVectorSearchIndexModel.cs | 29 ++++++++++++++ .../CreateVectorSearchIndexModel.cs | 32 +-------------- .../CreateVectorSearchIndexModelBase.cs | 40 +++++++++++++++++++ src/MongoDB.Driver/VectorQuantization.cs | 11 ++++- .../PipelineDefinitionBuilderTests.cs | 15 +++++++ .../Search/AtlasSearchIndexManagmentTests.cs | 12 +++++- 6 files changed, 106 insertions(+), 33 deletions(-) diff --git a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs index e7017a55c4f..54ddf82a19f 100644 --- a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs @@ -36,6 +36,17 @@ public sealed class CreateAutoEmbeddingVectorSearchIndexModel : Creat /// public VectorEmbeddingModality Modality { get; init; } = VectorEmbeddingModality.Text; + /// + /// The to use to search for top K-nearest neighbors. For auto-embedding indexes, + /// this defaults to when + /// is + /// or , and + /// when + /// is + /// or . + /// + public VectorSimilarity? Similarity { get; init; } + /// /// Initializes a new instance of the for a vector index /// that will automatically create embeddings from a given field in the document. The embedding model to use must @@ -93,6 +104,11 @@ public CreateAutoEmbeddingVectorSearchIndexModel WithIncludedStoredFi IncludedStoredFields = includedStoredFields, ExcludedStoredFields = null, Modality = Modality, + Similarity = Similarity, + Dimensions = Dimensions, + Quantization = Quantization, + HnswMaxEdges = HnswMaxEdges, + HnswNumEdgeCandidates = HnswNumEdgeCandidates, }; /// @@ -121,6 +137,11 @@ public CreateAutoEmbeddingVectorSearchIndexModel WithExcludedStoredFi ExcludedStoredFields = excludedStoredFields, IncludedStoredFields = null, Modality = Modality, + Similarity = Similarity, + Dimensions = Dimensions, + Quantization = Quantization, + HnswMaxEdges = HnswMaxEdges, + HnswNumEdgeCandidates = HnswNumEdgeCandidates, }; /// @@ -138,14 +159,22 @@ public CreateAutoEmbeddingVectorSearchIndexModel WithExcludedStoredFi /// internal override BsonDocument Render(RenderArgs renderArgs) { + var similarityValue = Similarity == VectorSimilarity.DotProduct + ? "dotProduct" // Because neither "DotProduct" or "dotproduct" are allowed. + : Similarity?.ToString().ToLowerInvariant(); + var vectorField = new BsonDocument { { "type", "autoEmbed" }, { "path", Field.Render(renderArgs).FieldName }, { "modality", Modality.ToString().ToLowerInvariant() }, { "model", AutoEmbeddingModelName }, + { "similarity", similarityValue, similarityValue != null }, + { "numDimensions", Dimensions, Dimensions != 0 }, }; + RenderCommonFieldElements(renderArgs, vectorField); + var fieldDocuments = new List { vectorField }; RenderFilterFields(renderArgs, fieldDocuments); diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs index 71c9ff7b0a2..1cae3a06bd7 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs @@ -31,27 +31,6 @@ public sealed class CreateVectorSearchIndexModel : CreateVectorSearch /// public VectorSimilarity Similarity { get; } - /// - /// Number of vector dimensions that vector search enforces at index-time and query-time. - /// - public int Dimensions { get; } - - /// - /// Type of automatic vector quantization for your vectors. - /// - public VectorQuantization? Quantization { get; init; } - - /// - /// Maximum number of edges (or connections) that a node can have in the Hierarchical Navigable Small Worlds graph. - /// - public int? HnswMaxEdges { get; init; } - - /// - /// Analogous to numCandidates at query-time, this parameter controls the maximum number of nodes to evaluate to - /// find the closest neighbors to connect to a new node. - /// - public int? HnswNumEdgeCandidates { get; init; } - /// /// Initializes a new instance of the class for a vector /// index where the vector embeddings are created manually. The required options for @@ -176,16 +155,7 @@ internal override BsonDocument Render(RenderArgs renderArgs) { "similarity", similarityValue }, }; - vectorField.Add("quantization", Quantization.ToString()?.ToLowerInvariant(), Quantization.HasValue); - - if (HnswMaxEdges != null || HnswNumEdgeCandidates != null) - { - vectorField.Add("hnswOptions", - new BsonDocument - { - { "maxEdges", HnswMaxEdges ?? 16 }, { "numEdgeCandidates", HnswNumEdgeCandidates ?? 100 } - }); - } + RenderCommonFieldElements(renderArgs, vectorField); var fieldDocuments = new List { vectorField }; RenderFilterFields(renderArgs, fieldDocuments); diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs index 6c59b1a69c6..09ad02b0acd 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs @@ -50,6 +50,28 @@ public abstract class CreateVectorSearchIndexModelBase : CreateSearch /// public IReadOnlyList> ExcludedStoredFields { get; protected init; } + /// + /// Number of vector dimensions that vector search enforces at index-time and query-time, or uses to build + /// the embeddings for auto-embedding indexes. + /// + public int Dimensions { get; init; } + + /// + /// Type of automatic vector quantization for your vectors. + /// + public VectorQuantization? Quantization { get; init; } + + /// + /// Maximum number of edges (or connections) that a node can have in the Hierarchical Navigable Small Worlds graph. + /// + public int? HnswMaxEdges { get; init; } + + /// + /// Analogous to numCandidates at query-time, this parameter controls the maximum number of nodes to evaluate to + /// find the closest neighbors to connect to a new node. + /// + public int? HnswNumEdgeCandidates { get; init; } + /// /// Initializes a new instance of the class for a vector /// index where the vector embeddings are created manually. The required options for @@ -117,4 +139,22 @@ private protected void RenderStoredSource(RenderArgs renderArgs, Bson indexDocument.Add("storedSource", new BsonDocument { { exclude ? "exclude" : "include", fields } }); } + + private protected void RenderCommonFieldElements(RenderArgs renderArgs, BsonDocument vectorField) + { + var quantizationValue = Quantization == VectorQuantization.BinaryNoRescore + ? "binaryNoRescore" + : Quantization?.ToString().ToLowerInvariant(); + + vectorField.Add("quantization", quantizationValue, quantizationValue != null); + + if (HnswMaxEdges != null || HnswNumEdgeCandidates != null) + { + vectorField.Add("hnswOptions", + new BsonDocument + { + { "maxEdges", HnswMaxEdges ?? 16 }, { "numEdgeCandidates", HnswNumEdgeCandidates ?? 100 } + }); + } + } } diff --git a/src/MongoDB.Driver/VectorQuantization.cs b/src/MongoDB.Driver/VectorQuantization.cs index 0b0fa37297c..d64be6d01ef 100644 --- a/src/MongoDB.Driver/VectorQuantization.cs +++ b/src/MongoDB.Driver/VectorQuantization.cs @@ -36,7 +36,16 @@ public enum VectorQuantization /// /// Indicates binary quantization, which transforms values to a single bit. /// To use this value, numDimensions must be a multiple of 8. - /// If precision is critical, select or instead of . + /// If precision is critical, select or instead of + /// or . /// Binary, + + /// + /// Indicates binary quantization, which transforms values to a single bit, but does not rescore the results. + /// To use this value, numDimensions must be a multiple of 8. + /// If precision is critical, select or instead of + /// or . + /// + BinaryNoRescore, } diff --git a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs index 757e7eb56c8..496afed9e57 100644 --- a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs @@ -643,6 +643,21 @@ public void VectorSearch_should_add_expected_stage_with_options() stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x', limit: 1, numCandidates: 123, index: 'index_name', filter : { $and : [{ x : { $eq : 1 } }, { y : { $eq : 2 } }] } } }"); } + [Fact] + public void VectorSearch_should_add_expected_stage_with_ReturnStoredSource() + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + ReturnStoredSource = true + }; + var result = pipeline.VectorSearch("x", new[] { 1.0, 2.0, 3.0 }, 1, options); + + var stages = RenderStages(result, BsonDocumentSerializer.Instance); + stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x', limit: 1, numCandidates: 10, index: 'index_name', returnStoredSource: true } }"); + } + [Fact] public void VectorSearch_should_throw_when_pipeline_is_null() { diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs index 1a7aafbbd79..fec68eebe70 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs @@ -533,7 +533,7 @@ public async Task Can_create_autoEmbed_vector_index_for_required_only_options( public async Task Can_create_autoEmbed_vector_index_for_all_options( [Values(false, true)] bool async) { - // Note that these tests pass with Atlas local, but fail on the CI. + // Note that these tests don't yet pass on real Atlas or Atlas local. SkipTests(); var indexName = "auto-embed-all" + (async ? "-async" : ""); @@ -542,6 +542,11 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( e => e.SomeText, indexName, "voyage-4") { Modality = VectorEmbeddingModality.Text, + Dimensions = 512, + Quantization = VectorQuantization.BinaryNoRescore, + Similarity = VectorSimilarity.Euclidean, + HnswMaxEdges = 18, + HnswNumEdgeCandidates = 102 }; var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); @@ -562,6 +567,11 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( indexField["path"].AsString.Should().Be("SomeText"); indexField["model"].AsString.Should().Be("voyage-4"); indexField["modality"].AsString.Should().Be("text"); + indexField["numDimensions"].AsInt32.Should().Be(512); + indexField["similarity"].AsString.Should().Be("euclidean"); + indexField["quantization"].AsString.Should().Be("binaryNoRescore"); + indexField["hnswOptions"].AsBsonDocument["maxEdges"].AsInt32.Should().Be(18); + indexField["hnswOptions"].AsBsonDocument["numEdgeCandidates"].AsInt32.Should().Be(102); indexField.Contains("quantization").Should().Be(false); indexField.Contains("numDimensions").Should().Be(false); From 24641bba94aa7f478fef6d77012fd93dfd4ce608 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Mon, 9 Mar 2026 11:09:24 +0000 Subject: [PATCH 3/5] CSHARP-5762: Vector search against nested embeddings and arrays of embeddings --- ...eateAutoEmbeddingVectorSearchIndexModel.cs | 2 +- .../CreateVectorSearchIndexModel.cs | 2 +- .../CreateVectorSearchIndexModelBase.cs | 38 +- src/MongoDB.Driver/FieldDefinition.cs | 31 +- .../Linq/LinqProviderAdapter.cs | 14 +- .../PipelineStageDefinitionBuilder.cs | 22 +- src/MongoDB.Driver/RenderArgs.cs | 6 + src/MongoDB.Driver/SearchScoreFunction.cs | 32 + src/MongoDB.Driver/VectorSearchOptions.cs | 11 + .../Linq/LinqProviderAdapterTests.cs | 7 +- .../PipelineDefinitionBuilderTests.cs | 80 ++ .../Search/AtlasSearchIndexManagmentTests.cs | 149 ++- .../Search/AutoEmbedVectorSearchTests.cs | 15 + .../Search/VectorSearchTests.cs | 1062 ++++++++++++++++- 14 files changed, 1428 insertions(+), 43 deletions(-) create mode 100644 src/MongoDB.Driver/SearchScoreFunction.cs diff --git a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs index 54ddf82a19f..73359f5d2e8 100644 --- a/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateAutoEmbeddingVectorSearchIndexModel.cs @@ -179,7 +179,7 @@ internal override BsonDocument Render(RenderArgs renderArgs) RenderFilterFields(renderArgs, fieldDocuments); var indexDefinition = new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; - RenderStoredSource(renderArgs, indexDefinition); + RenderCommonElements(renderArgs, indexDefinition); return indexDefinition; } diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs index 1cae3a06bd7..ae243c1c839 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModel.cs @@ -161,7 +161,7 @@ internal override BsonDocument Render(RenderArgs renderArgs) RenderFilterFields(renderArgs, fieldDocuments); var indexDefinition = new BsonDocument { { "fields", new BsonArray(fieldDocuments) } }; - RenderStoredSource(renderArgs, indexDefinition); + RenderCommonElements(renderArgs, indexDefinition); return indexDefinition; } diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs index 09ad02b0acd..26912631021 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs @@ -119,38 +119,48 @@ private protected void RenderFilterFields(RenderArgs renderArgs, List } /// - /// Called by subclasses to render the "storedSource" in the index definition. + /// Called by subclasses to render common top-level elements in the index definition. /// /// The render args. - /// The index document into which the stored source fields will go. - private protected void RenderStoredSource(RenderArgs renderArgs, BsonDocument indexDocument) + /// The index document into which the elements will go. + private protected void RenderCommonElements(RenderArgs renderArgs, BsonDocument indexDocument) { - var exclude = ExcludedStoredFields?.Any() == true; - if (!exclude && IncludedStoredFields?.Any() != true) + var fieldName = Field.Render(renderArgs).FieldName; + var dotPos = fieldName.LastIndexOf('.'); + if (dotPos > 0) { - return; + indexDocument.Add("nestedRoot", fieldName.Substring(0, dotPos)); } - var fields = new BsonArray(); - foreach (var field in exclude ? ExcludedStoredFields : IncludedStoredFields) + var exclude = ExcludedStoredFields?.Any() == true; + if (exclude || IncludedStoredFields?.Any() == true) { - fields.Add(field.Render(renderArgs).FieldName); - } + var fields = new BsonArray(); + foreach (var field in exclude ? ExcludedStoredFields : IncludedStoredFields) + { + fields.Add(field.Render(renderArgs).FieldName); + } - indexDocument.Add("storedSource", new BsonDocument { { exclude ? "exclude" : "include", fields } }); + indexDocument.Add("storedSource", new BsonDocument { { exclude ? "exclude" : "include", fields } }); + } } - private protected void RenderCommonFieldElements(RenderArgs renderArgs, BsonDocument vectorField) + /// + /// Called by subclasses to render common elements in a field of the index definition. + /// + /// The render args. + /// The field document into which the elements will go. + private protected void RenderCommonFieldElements(RenderArgs renderArgs, BsonDocument fieldDocument) { var quantizationValue = Quantization == VectorQuantization.BinaryNoRescore ? "binaryNoRescore" : Quantization?.ToString().ToLowerInvariant(); - vectorField.Add("quantization", quantizationValue, quantizationValue != null); + fieldDocument.Add("quantization", quantizationValue, quantizationValue != null); if (HnswMaxEdges != null || HnswNumEdgeCandidates != null) { - vectorField.Add("hnswOptions", + fieldDocument.Add("hnswOptions", new BsonDocument { { "maxEdges", HnswMaxEdges ?? 16 }, { "numEdgeCandidates", HnswNumEdgeCandidates ?? 100 } diff --git a/src/MongoDB.Driver/FieldDefinition.cs b/src/MongoDB.Driver/FieldDefinition.cs index 6a3f1319da6..ebdb1fd532b 100644 --- a/src/MongoDB.Driver/FieldDefinition.cs +++ b/src/MongoDB.Driver/FieldDefinition.cs @@ -57,6 +57,22 @@ public IBsonSerializer FieldSerializer { get { return _fieldSerializer; } } + + internal static string RemoveSubPathRoot(string fieldName, string subPathRoot) + { + if (subPathRoot == null) + { + return fieldName; + } + + if (fieldName.StartsWith(subPathRoot + ".", StringComparison.Ordinal)) + { + return fieldName.Remove(0, subPathRoot.Length + 1); + } + + throw new InvalidOperationException( + $"The field '{fieldName}' is not part of the nested document '{subPathRoot}', which is the root of this search. Search over nested documents requires filters either on the root or on at the nested document level being searched."); + } } /// @@ -242,7 +258,8 @@ public LambdaExpression Expression /// public override RenderedFieldDefinition Render(RenderArgs args) { - return LinqProviderAdapter.TranslateExpressionToField(_expression, args.DocumentSerializer, args.SerializerRegistry, args.TranslationOptions); + return LinqProviderAdapter.TranslateExpressionToField(_expression, args.DocumentSerializer, + args.SerializerRegistry, args.TranslationOptions, args.SubPathRoot); } } @@ -275,7 +292,9 @@ public Expression> Expression /// public override RenderedFieldDefinition Render(RenderArgs args) { - return LinqProviderAdapter.TranslateExpressionToField(_expression, args.DocumentSerializer, args.SerializerRegistry, args.TranslationOptions, args.PathRenderArgs.AllowScalarValueForArray); + return LinqProviderAdapter.TranslateExpressionToField(_expression, args.DocumentSerializer, + args.SerializerRegistry, args.TranslationOptions, args.PathRenderArgs.AllowScalarValueForArray, + args.SubPathRoot); } } @@ -303,6 +322,8 @@ public override RenderedFieldDefinition Render(RenderArgs args) IBsonSerializer resolvedSerializer; StringFieldDefinitionHelper.Resolve(_fieldName, args.DocumentSerializer, out resolvedName, out resolvedSerializer); + resolvedName = RenderedFieldDefinition.RemoveSubPathRoot(resolvedName, args.SubPathRoot); + return new RenderedFieldDefinition(resolvedName, resolvedSerializer); } } @@ -351,6 +372,8 @@ public override RenderedFieldDefinition Render(RenderArgs arg valueSerializer = args.SerializerRegistry.GetSerializer(); } + resolvedName = RenderedFieldDefinition.RemoveSubPathRoot(resolvedName, args.SubPathRoot); + return new RenderedFieldDefinition(resolvedName, fieldSerializer, valueSerializer, underlyingSerializer); } } @@ -451,7 +474,9 @@ public UntypedFieldDefinitionAdapter(FieldDefinition adaptee) public override RenderedFieldDefinition Render(RenderArgs args) { var rendered = _adaptee.Render(args); - return new RenderedFieldDefinition(rendered.FieldName, rendered.UnderlyingSerializer); + var fieldName = RenderedFieldDefinition.RemoveSubPathRoot(rendered.FieldName, args.SubPathRoot); + + return new RenderedFieldDefinition(fieldName, rendered.UnderlyingSerializer); } } } diff --git a/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs b/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs index 2766972dc68..745be985e85 100644 --- a/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs +++ b/src/MongoDB.Driver/Linq/LinqProviderAdapter.cs @@ -71,7 +71,8 @@ internal static RenderedFieldDefinition TranslateExpressionToField( LambdaExpression expression, IBsonSerializer documentSerializer, IBsonSerializerRegistry serializerRegistry, - ExpressionTranslationOptions translationOptions) + ExpressionTranslationOptions translationOptions, + string subPathRoot) { expression = (LambdaExpression)LinqExpressionPreprocessor.Preprocess(expression); var parameter = expression.Parameters.Single(); @@ -81,7 +82,9 @@ internal static RenderedFieldDefinition TranslateExpressionToField( var body = RemovePossibleConvertToObject(expression.Body); var fieldTranslation = ExpressionToFilterFieldTranslator.Translate(context, body); - return new RenderedFieldDefinition(fieldTranslation.Ast.Path, fieldTranslation.Serializer); + var fieldName = RenderedFieldDefinition.RemoveSubPathRoot(fieldTranslation.Ast.Path, subPathRoot); + + return new RenderedFieldDefinition(fieldName, fieldTranslation.Serializer); static Expression RemovePossibleConvertToObject(Expression expression) { @@ -101,7 +104,8 @@ internal static RenderedFieldDefinition TranslateExpressionToField documentSerializer, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions, - bool allowScalarValueForArrayField) + bool allowScalarValueForArrayField, + string subPathRoot) { expression = (Expression>)LinqExpressionPreprocessor.Preprocess(expression); var parameter = expression.Parameters.Single(); @@ -114,7 +118,9 @@ internal static RenderedFieldDefinition TranslateExpressionToField; var valueSerializer = (IBsonSerializer)FieldValueSerializerHelper.GetSerializerForValueType(underlyingSerializer, serializerRegistry, typeof(TField), allowScalarValueForArrayField); - return new RenderedFieldDefinition(fieldTranslation.Ast.Path, fieldSerializer, valueSerializer, underlyingSerializer); + var fieldName = RenderedFieldDefinition.RemoveSubPathRoot(fieldTranslation.Ast.Path, subPathRoot); + + return new RenderedFieldDefinition(fieldName, fieldSerializer, valueSerializer, underlyingSerializer); } internal static BsonDocument TranslateExpressionToElemMatchFilter( diff --git a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs index a49d06a610d..95aa5a548c2 100644 --- a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs @@ -2168,17 +2168,35 @@ public static PipelineStageDefinition VectorSearch( { ClientSideProjectionHelper.ThrowIfClientSideProjection(args.DocumentSerializer, operatorName); + var path = field.Render(args).FieldName; + var dotPos = path.LastIndexOf('.'); + var nestedRoot = dotPos > 0 ? path.Substring(0, dotPos) : null; + var vectorSearchOperator = new BsonDocument { - { "path", field.Render(args).FieldName }, + { "path", path }, { "limit", limit }, { "numCandidates", options?.NumberOfCandidates ?? limit * 10, options?.Exact != true }, { "index", options?.IndexName ?? "default" }, - { "filter", () => options?.Filter.Render(args with { RenderDollarForm = true }), options?.Filter != null }, + { nestedRoot != null ? "parentFilter" : "filter", () => options?.Filter.Render(args with { RenderDollarForm = true }), options?.Filter != null }, { "exact", true, options?.Exact == true }, { "returnStoredSource", true, options?.ReturnStoredSource == true }, }; + if (nestedRoot != null && options?.NestedFilter != null) + { + vectorSearchOperator.Add("filter", options.NestedFilter.Render( + (args with { SubPathRoot = nestedRoot }) with { RenderDollarForm = true })); + } + + if (options?.EmbeddedScoreMode != null) + { + vectorSearchOperator.Add("nestedOptions", new BsonDocument + { + { "scoreMode", options.EmbeddedScoreMode == SearchScoreFunction.Average ? "avg" : "max" } + }); + } + if (queryVector.Vector is BsonString bsonString) { vectorSearchOperator["query"] = new BsonDocument { { "text", bsonString } }; diff --git a/src/MongoDB.Driver/RenderArgs.cs b/src/MongoDB.Driver/RenderArgs.cs index 1f6e2452a23..06f9db4d608 100644 --- a/src/MongoDB.Driver/RenderArgs.cs +++ b/src/MongoDB.Driver/RenderArgs.cs @@ -33,6 +33,7 @@ public record struct RenderArgs { private readonly IBsonSerializer _documentSerializer = default; private readonly PathRenderArgs _pathRenderArgs = default; + private readonly string _subPathRoot = default; private readonly bool _renderDollarForm = default; private readonly bool _renderForElemMatch = false; private readonly bool _renderForFind = false; @@ -91,6 +92,11 @@ public readonly IBsonSerializer DocumentSerializer /// public readonly PathRenderArgs PathRenderArgs { get => _pathRenderArgs; init => _pathRenderArgs = value; } + /// + /// Gets the sub-path that should be used for the root of the rendered document. + /// + public readonly string SubPathRoot { get => _subPathRoot; init => _subPathRoot = value; } + /// /// Gets the value indicating whether full dollar form should be rendered. /// diff --git a/src/MongoDB.Driver/SearchScoreFunction.cs b/src/MongoDB.Driver/SearchScoreFunction.cs new file mode 100644 index 00000000000..410fa072192 --- /dev/null +++ b/src/MongoDB.Driver/SearchScoreFunction.cs @@ -0,0 +1,32 @@ +/* Copyright 2010-present MongoDB Inc. + * + * 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 + * + * http://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. + */ + +namespace MongoDB.Driver; + +/// +/// The function to use when scoring results from a search on embedded documents. +/// +public enum SearchScoreFunction +{ + /// + /// Use the average score. + /// + Average, + + /// + /// Use the maximum score. + /// + Maximum +} diff --git a/src/MongoDB.Driver/VectorSearchOptions.cs b/src/MongoDB.Driver/VectorSearchOptions.cs index 341cfb7e445..d8c24e7d9cd 100644 --- a/src/MongoDB.Driver/VectorSearchOptions.cs +++ b/src/MongoDB.Driver/VectorSearchOptions.cs @@ -26,6 +26,12 @@ public sealed class VectorSearchOptions /// public FilterDefinition Filter { get; set; } + /// + /// Gets or sets the nested filter. This can only be used when the vector search is performed on a nested + /// document, in which case this filter can be used as an additional filter on the nested documents. + /// + public FilterDefinition NestedFilter { get; set; } + /// /// Gets or sets the name of the index. /// @@ -52,5 +58,10 @@ public sealed class VectorSearchOptions /// or return only stored source fields directly from Atlas Search. /// public bool ReturnStoredSource { get; set; } + + /// + /// Gets or sets the function to use when scoring results from a search on embedded documents. + /// + public SearchScoreFunction? EmbeddedScoreMode { get; set; } } } diff --git a/tests/MongoDB.Driver.Tests/Linq/LinqProviderAdapterTests.cs b/tests/MongoDB.Driver.Tests/Linq/LinqProviderAdapterTests.cs index f6f0d15f647..c9b572a7229 100644 --- a/tests/MongoDB.Driver.Tests/Linq/LinqProviderAdapterTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/LinqProviderAdapterTests.cs @@ -63,7 +63,8 @@ public void TranslateExpressionToField_with_untyped_lambda_should_return_expecte var serializerRegistry = BsonSerializer.SerializerRegistry; var documentSerializer = serializerRegistry.GetSerializer(); - var result = LinqProviderAdapter.TranslateExpressionToField(expression, documentSerializer, serializerRegistry, translationOptions: null); + var result = LinqProviderAdapter.TranslateExpressionToField(expression, documentSerializer, + serializerRegistry, translationOptions: null, subPathRoot: null); result.FieldName.Should().Be("X"); result.FieldSerializer.Should().BeOfType(typeof(Int32Serializer)); @@ -76,7 +77,9 @@ public void TranslateExpressionToField_with_typed_lambda_should_return_expected_ var serializerRegistry = BsonSerializer.SerializerRegistry; var documentSerializer = serializerRegistry.GetSerializer(); - var result = LinqProviderAdapter.TranslateExpressionToField(expression, documentSerializer, serializerRegistry, translationOptions: null, allowScalarValueForArrayField: false); + var result = LinqProviderAdapter.TranslateExpressionToField(expression, documentSerializer, + serializerRegistry, translationOptions: null, allowScalarValueForArrayField: false, + subPathRoot: null); result.FieldName.Should().Be("X"); result.FieldSerializer.Should().BeOfType(typeof(Int32Serializer)); diff --git a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs index 496afed9e57..d04392dbbf9 100644 --- a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs @@ -21,6 +21,7 @@ using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver.GeoJsonObjectModel; using MongoDB.Driver.Search; +using MongoDB.TestHelpers.XunitExtensions; using Moq; using Xunit; @@ -658,6 +659,85 @@ public void VectorSearch_should_add_expected_stage_with_ReturnStoredSource() stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x', limit: 1, numCandidates: 10, index: 'index_name', returnStoredSource: true } }"); } + [Fact] + public void VectorSearch_should_add_expected_stage_with_nested_options() + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + EmbeddedScoreMode = SearchScoreFunction.Average, + }; + var result = pipeline.VectorSearch("x", new[] { 1.0, 2.0, 3.0 }, 1, options); + + var stages = RenderStages(result, BsonDocumentSerializer.Instance); + stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x', limit: 1, numCandidates: 10, index: 'index_name', nestedOptions: { scoreMode: 'avg' } } }"); + } + + [Theory] + [ParameterAttributeData] + public void VectorSearch_should_add_expected_stage_with_parent_filters([Values(false, true)] bool expressions) + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + }; + + if (expressions) + { + options.Filter = Builders.Filter.Gt(m => m.Year, 1900); + options.NestedFilter = Builders.Filter.Lt(m => m.Plot.Rating, 6) + & Builders.Filter.Eq(m => m.Plot.Synced, true); + } + else + { + options.Filter = Builders.Filter.Gt("Year", 1900); + options.NestedFilter = Builders.Filter.Lt("Plot.Rating", 6) + & Builders.Filter.Eq("Plot.Synced", true); + } + + var result = pipeline.VectorSearch(m => m.Plot.PlotEmbedding, new[] { 1.0, 2.0, 3.0 }, 1, options); + + var stages = RenderStages(result, BsonSerializer.SerializerRegistry.GetSerializer()); + stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'Plot.PlotEmbedding', limit: 1, numCandidates: 10, index: 'index_name', filter: { '$and' : [{ Rating: { '$lt' : 6 } }, { Synced: { '$eq' : true } }] }, parentFilter: { 'Year' : { '$gt' : 1900 } } } }"); + } + + private class MovieWithPlot + { + public int Year { get; set; } + public NestedPlot Plot { get; set; } + } + + private class NestedPlot + { + public bool Synced { get; set; } + public int Rating { get; set; } + public float[] PlotEmbedding { get; set; } + } + + [Theory] + [ParameterAttributeData] + public void VectorSearch_should_throw_when_filter_is_at_wrong_level([Values(false, true)] bool expressions) + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + }; + + options.NestedFilter = expressions + ? Builders.Filter.Lt(m => m.Year, 1900) + : Builders.Filter.Lt("Year", 1900); + + var result = pipeline.VectorSearch(m => m.Plot.PlotEmbedding, new[] { 1.0, 2.0, 3.0 }, 1, options); + + var exception = Record.Exception(() => RenderStages(result, BsonSerializer.SerializerRegistry.GetSerializer())); + + exception.Should().BeOfType() + .Which.Message.Should().Contain("The field 'Year' is not part of the nested document 'Plot', which is the root of this search."); + } + [Fact] public void VectorSearch_should_throw_when_pipeline_is_null() { diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs index fec68eebe70..3c6bb4b31e0 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchIndexManagmentTests.cs @@ -412,8 +412,10 @@ public async Task Can_create_Atlas_vector_index_for_all_options_with_filters( var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var indexDefinition = index["latestDefinition"]; - var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -465,8 +467,10 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var indexDefinition = index["latestDefinition"]; - var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -492,6 +496,107 @@ public async Task Can_create_Atlas_vector_index_for_required_only_options_with_f excluded[1].AsString.Should().Be("SomeText"); } + [Theory(Timeout = Timeout)] + [ParameterAttributeData] + public async Task Can_create_Atlas_vector_index_for_nested_field( + [Values(false, true)] bool async) + { + var indexName = "vector-nested" + (async ? "-async" : ""); + + var indexModel = new CreateVectorSearchIndexModel( + e => e.NestedEntity.NestedFloats, + indexName, + VectorSimilarity.Cosine, + dimensions: 512, + e => e.Filter1, e => e.Filter2, e => e.Filter3, e => e.NestedEntity.NestedFilter1, + e => e.NestedEntity.NestedFilter2, e => e.NestedEntity.NestedFilter3) + { + HnswMaxEdges = 18, + HnswNumEdgeCandidates = 102, + Quantization = VectorQuantization.Scalar, + }; + + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); + var createdName = async + ? await collection.SearchIndexes.CreateOneAsync(indexModel) + : collection.SearchIndexes.CreateOne(indexModel); + + createdName.Should().Be(indexName); + + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; + index["type"].AsString.Should().Be("vectorSearch"); + + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition["nestedRoot"].AsString.Should().Be("NestedEntity"); + + var fields = indexDefinition["fields"].AsBsonArray; + fields.Count.Should().Be(7); + + var indexField = fields[0].AsBsonDocument; + indexField["type"].AsString.Should().Be("vector"); + indexField["path"].AsString.Should().Be("NestedEntity.NestedFloats"); + indexField["numDimensions"].AsInt32.Should().Be(512); + indexField["similarity"].AsString.Should().Be("cosine"); + indexField["quantization"].AsString.Should().Be("scalar"); + indexField["hnswOptions"].AsBsonDocument["maxEdges"].AsInt32.Should().Be(18); + indexField["hnswOptions"].AsBsonDocument["numEdgeCandidates"].AsInt32.Should().Be(102); + + for (var i = 1; i <= 6; i++) + { + var filterField = fields[i].AsBsonDocument; + filterField["type"].AsString.Should().Be("filter"); + filterField["path"].AsString.Should().Be(i <= 3 ? $"Filter{i}" : $"NestedEntity.NestedFilter{i - 3}"); + } + } + + [Theory(Timeout = Timeout)] + [ParameterAttributeData] + public async Task Can_create_Atlas_vector_index_for_nested_field_with_strings( + [Values(false, true)] bool async) + { + var indexName = "vector-nested-strings" + (async ? "-async" : ""); + + var indexModel = new CreateVectorSearchIndexModel( + "NestedEntity.NestedFloats", + indexName, + VectorSimilarity.Euclidean, + dimensions: 512, + "Filter1", "Filter2", "Filter3", "NestedEntity.NestedFilter1", "NestedEntity.NestedFilter2", + "NestedEntity.NestedFilter3"); + + var collection = _database.GetCollection(_collection.CollectionNamespace.CollectionName); + var createdName = async + ? await collection.SearchIndexes.CreateOneAsync(indexModel) + : collection.SearchIndexes.CreateOne(indexModel); + + createdName.Should().Be(indexName); + + var index = (await GetIndexes(async, expectTimeout: false, indexName))[0]; + index["type"].AsString.Should().Be("vectorSearch"); + + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition["nestedRoot"].AsString.Should().Be("NestedEntity"); + + var fields = indexDefinition["fields"].AsBsonArray; + fields.Count.Should().Be(7); + + var indexField = fields[0].AsBsonDocument; + indexField["type"].AsString.Should().Be("vector"); + indexField["path"].AsString.Should().Be("NestedEntity.NestedFloats"); + indexField["numDimensions"].AsInt32.Should().Be(512); + indexField["similarity"].AsString.Should().Be("euclidean"); + + indexField.Contains("quantization").Should().Be(false); + indexField.Contains("hnswOptions").Should().Be(false); + + for (var i = 1; i <= 6; i++) + { + var filterField = fields[i].AsBsonDocument; + filterField["type"].AsString.Should().Be("filter"); + filterField["path"].AsString.Should().Be(i <= 3 ? $"Filter{i}" : $"NestedEntity.NestedFilter{i - 3}"); + } + } + [Theory(Timeout = Timeout)] [ParameterAttributeData] public async Task Can_create_autoEmbed_vector_index_for_required_only_options( @@ -514,7 +619,10 @@ public async Task Can_create_autoEmbed_vector_index_for_required_only_options( var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(1); var indexField = fields[0].AsBsonDocument; @@ -559,7 +667,10 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var fields = index["latestDefinition"].AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(1); var indexField = fields[0].AsBsonDocument; @@ -572,10 +683,6 @@ public async Task Can_create_autoEmbed_vector_index_for_all_options( indexField["quantization"].AsString.Should().Be("binaryNoRescore"); indexField["hnswOptions"].AsBsonDocument["maxEdges"].AsInt32.Should().Be(18); indexField["hnswOptions"].AsBsonDocument["numEdgeCandidates"].AsInt32.Should().Be(102); - - indexField.Contains("quantization").Should().Be(false); - indexField.Contains("numDimensions").Should().Be(false); - indexField.Contains("similarity").Should().Be(false); } [Theory(Timeout = Timeout)] @@ -606,8 +713,10 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_text( var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var indexDefinition = index["latestDefinition"]; - var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -662,8 +771,10 @@ public async Task Can_create_autoEmbed_vector_index_with_filters_as_expressions( var index = (await GetIndexes(async, expectTimeout: true, indexName))[0]; index["type"].AsString.Should().Be("vectorSearch"); - var indexDefinition = index["latestDefinition"]; - var fields = indexDefinition.AsBsonDocument["fields"].AsBsonArray; + var indexDefinition = index["latestDefinition"].AsBsonDocument; + indexDefinition.Contains("nestedRoot").Should().Be(false); + + var fields = indexDefinition["fields"].AsBsonArray; fields.Count.Should().Be(4); var indexField = fields[0].AsBsonDocument; @@ -698,6 +809,16 @@ private class EntityWithVector public string Filter2 { get; set; } public int Filter3 { get; set; } public string SomeText { get; set; } + public NestedEntityWithVector NestedEntity { get; set; } + } + + private class NestedEntityWithVector + { + public float[] NestedFloats { get; set; } + public bool NestedFilter1 { get; set; } + public string NestedFilter2 { get; set; } + public int NestedFilter3 { get; set; } + public string NestedText { get; set; } } private static string CreateIndexName(string baseName, bool async, bool includeFields) diff --git a/tests/MongoDB.Driver.Tests/Search/AutoEmbedVectorSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/AutoEmbedVectorSearchTests.cs index 600d0ce0a2e..2174571fca3 100644 --- a/tests/MongoDB.Driver.Tests/Search/AutoEmbedVectorSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AutoEmbedVectorSearchTests.cs @@ -215,5 +215,20 @@ public class Movie [BsonElement("score")] public double Score { get; set; } + + [BsonElement("proposal")] + public Proposal Proposal { get; set; } + } + + public class Proposal + { + [BsonElement("title")] + public string Outline { get; set; } + + [BsonElement("receivedYear")] + public int ReceivedYear { get; set; } + + [BsonElement("initiallyApproved")] + public bool InitiallyApproved { get; set; } } } diff --git a/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs index a912c49b97a..8e164b36cc3 100644 --- a/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/VectorSearchTests.cs @@ -13,14 +13,17 @@ * limitations under the License. */ +using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using FluentAssertions; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver.Core.TestHelpers.Logging; using Xunit; using Xunit.Abstractions; +using Xunit.Sdk; namespace MongoDB.Driver.Tests.Search { @@ -82,8 +85,7 @@ public void VectorSearch() var options = new VectorSearchOptions() { Filter = Builders.Filter.Gt("runtime", 1) & Builders.Filter.Gt("year", 1900), - IndexName = "sample_mflix__embedded_movies", - ReturnStoredSource = true + IndexName = "sample_mflix__embedded_movies" }; var results = GetEmbeddedMoviesCollection() @@ -130,6 +132,1018 @@ public void VectorSearchExact() results.Should().OnlyContain(m => m.Score > 0.9); } + [Fact] + public void VectorSearch_on_embedded_documents() + { + SkipTests(); + + var nestedVectorCollection = + _mongoClient.GetDatabase("dotnet-test").GetCollection(GetRandomName()); + var nestedVectorIndexName = GetRandomName(); + + List movies = + [ + new MovieWithPlot + { + Title = @"Scarface", + Year = 1932, + Available = true, + Plot = new NestedPlot + { + Plot = + @"An ambitious and near insanely violent gangster climbs the ladder of success in the mob, but his weaknesses prove to be his downfall.", + Rating = 5, + PlotEmbedding = + [ + -0.0155797182f, -0.034283191f, 0.0152282966f, -0.0426131971f, -0.0208510514f, + 0.0263436511f, -0.00498824334f, -0.00442531705f, -0.0238446482f, -0.0199139267f, + 0.0279575903f, 0.0079200156f, 0.0126381842f, 0.00531038037f, 0.0134061072f, + -0.0202263016f, 0.0390208811f, -0.0109656751f, 0.00273165689f, -0.014863858f, + -0.00591560733f, -0.00420079706f, -0.0193672683f, 0.00133572984f, 0.0049589579f, + 0.00872047711f, 0.0100806113f, -0.0188206118f, 0.0252243057f, -0.0131848408f, + 0.0289467778f, -0.000112259877f, 0.00356628466f, -0.00347192143f, -0.0136273727f, + -0.0103669558f, -0.000123445192f, -0.0103083849f, -0.0122216837f, -0.0109982137f, + 0.0150200464f, -0.00348493713f, -0.00355652301f, -0.0292591546f, -0.0199659877f, + -0.0106207607f, 0.00129342906f, -0.0194974262f, -0.0303524677f, 0.00359882391f, + 0.0109851984f, 0.00663146749f, -0.0128724659f, -0.0140568893f, 0.00443507871f, + 0.0037159645f, 0.00536244269f, 0.00313026085f, 0.00114456262f, -0.00265519018f, + 0.00866190717f, -0.00901332963f, -0.00413246499f, -0.0115513783f, 0.00555442367f, + 0.0054470445f, -0.0215408802f, 0.00568457972f, -0.00269423705f, -0.0147597333f, + 0.040686883f, 0.0346215963f, 0.00366064813f, -0.00379080442f, 0.0156838428f, + -0.0061075883f, -0.0263046045f, 0.00940379873f, 0.000938752899f, 0.0138486391f, + 0.010894089f, -0.0229726005f, -0.018130783f, 0.0253284313f, 0.00687876483f, + 0.00751002319f, -0.0113170976f, 0.0173368305f, -0.00783541426f, -0.00512165343f, + -0.0150981396f, 0.00272189523f, 0.0210072398f, 0.0119418474f, -0.0188856907f, + -0.00312863407f, -0.0265519004f, -0.0012560091f, 0.00475070765f, -0.0280356836f, + 0.00948189199f, -0.00859682914f, -0.0117205819f, -0.0066900379f, -0.0181698296f, + -0.012748817f, 0.00017032183f, -0.0105491746f, 0.0317321233f, -0.000614988909f, + -0.0145775145f, 0.013204365f, 0.0351422206f, -0.045554731f, 0.0100675961f, + -0.035506662f, 0.0458150469f, -0.00858381297f, 0.0253024008f, -0.0251722429f, + 0.00129505596f, 0.0298839044f, 0.0230767261f, -0.00692431955f, -0.00558696268f, + -0.00132352766f, -0.00133003551f, -0.0237925854f, -0.00107704406f, 0.00252666068f, + 0.0241830554f, 0.0120785115f, 0.00533315772f, -0.00689178007f, -0.0136013413f, + 0.0132499197f, -2.18622044E-05f, -0.011212972f, -0.00675511593f, -0.0269684009f, + 0.0137835601f, 0.0178184081f, -0.00695035048f, 0.0114537617f, 0.000864726433f, + -0.0034979526f, 0.00594814634f, 0.0217230991f, 0.00243555126f, -0.0219703969f, + 0.0281137787f, -0.0256147757f, 0.0123388246f, -0.0159701873f, -0.00114374922f, + 0.0252112914f, -0.0128008798f, 0.0051899855f, -0.0219573807f, -0.00427889079f, + 0.0102693383f, 0.0146035459f, -0.0186383929f, -0.0115253469f, 0.0204605833f, + 0.0301702488f, 0.0037419959f, -0.000241602771f, 0.0119418474f, -0.0221135691f, + 0.0272287149f, 0.0184301436f, -0.0055804546f, 0.0200961456f, 0.0119483555f, + 0.0198878944f, 0.00385262887f, 0.0181047525f, -0.0254716035f, -0.00931919646f, + 0.0095274467f, 0.00391445309f, 0.0253935102f, 0.0154495621f, -0.0125405667f, + 0.00980728306f, 0.00528760301f, -0.00116083224f, -0.00323275896f, -0.0041910354f, + -0.00020479293f, 0.00657615112f, -0.00584727526f, 3.20815125E-05f, -0.672648191f, + -0.0176752359f, -0.024417337f, 0.00992442388f, -0.00323275896f, 0.0176101588f, + 0.00488086417f, 0.0125210434f, 0.00735383527f, 0.0127813565f, 0.0048515792f, + 0.00925411843f, 0.00889618881f, -0.0100545799f, -0.0228684749f, -0.0225430857f, + 0.0113236047f, -0.0540929921f, -0.0212154891f, 0.0083365161f, -0.000446192338f, + 0.0233630706f, -0.0142781548f, -0.0105621899f, 0.00933221262f, 0.00965109561f, + 0.0302223116f, -0.0270725265f, -0.00565204071f, 0.000524692878f, -0.02652587f, + 0.024990024f, 0.0049849893f, 0.00954697002f, 0.0531558655f, -0.0408691019f, + -0.0142391082f, 0.0231027566f, 0.0016033639f, 0.0211634263f, -0.00416175043f, + -0.00782890618f, 0.0019669882f, -0.0155406715f, -0.00698939757f, -0.0131262708f, + 0.0323829055f, -0.0333720967f, 0.007431929f, 0.00261288928f, 0.00468562962f, + 0.00357604655f, 0.010959167f, 0.00605877955f, 0.0033645425f, 0.0136664193f, + 0.013965779f, 0.00704796799f, -0.0120134335f, -0.0202653483f, 0.000388638815f, + -0.00101603323f, -0.0049849893f, -0.00674210023f, 0.00681368634f, 0.0276191831f, + -0.0184561741f, 0.0177272987f, 0.010640284f, -0.00981379114f, -0.000550724159f, + -0.00577568915f, -0.0144733889f, -0.0138095915f, 0.00987886917f, 0.0226732418f, + 0.0317581557f, -0.0058244979f, 0.00463031325f, -0.0142521234f, 0.00562275574f, + -0.0070674913f, -0.0163216107f, 0.00792652369f, 0.00982680637f, -0.00355652301f, + -0.0234932266f, 0.00431468384f, 0.00549259922f, -0.0137184821f, 0.0124559654f, + 0.00811525062f, -0.0137705449f, -0.0184171274f, 0.0133019816f, 0.00802414119f, + 0.00355977705f, 0.00487110252f, 0.0110828159f, -0.0447217301f, -0.00803715643f, + -0.007946047f, 0.00234769564f, 0.00935173593f, 0.0103669558f, 0.0123323165f, + 0.00288947159f, 0.00849270355f, 0.0463356711f, -0.0113170976f, 0.0149679836f, + -0.00908491481f, -0.0039990549f, -0.0142130768f, -0.0243262276f, -0.0274369642f, + 0.0197317079f, -0.00807620306f, 0.0181698296f, -0.0365218781f, -0.00761414832f, + -0.00423333608f, 0.027358871f, -0.00140894286f, -0.00406087888f, 0.00676162401f, + -0.00599044748f, -0.01652986f, -0.0341270007f, 0.0204996299f, -0.0094298292f, + -0.0255627129f, 0.0205907393f, -0.00905237626f, 0.0248989146f, -0.00257058837f, + -0.00557069294f, -0.00685273344f, 0.0179485641f, -0.00433420762f, -0.0095534781f, + 0.000812257174f, 0.0184171274f, 0.0185602996f, -0.00911094621f, -0.031393718f, + -0.0135492794f, -0.00773128867f, -0.027489027f, 0.0223218184f, -0.0136794355f, + -0.0133800758f, -0.0067160693f, 0.0169593766f, 0.015892094f, -0.00695035048f, + -0.0192761589f, 0.0113626523f, -0.0147857647f, -0.0264347605f, 0.000286750786f, + 0.0117335971f, -0.0266299956f, 0.0254065245f, 0.0149549684f, -0.00383310532f, + 0.0225430857f, 0.0155146401f, -0.00749049941f, -0.00980728306f, 0.0060945726f, + -0.0233760849f, 0.000196149733f, 0.0111413859f, -0.00508586038f, -0.00314002275f, + 0.0074449447f, 0.0171806421f, 0.0142000606f, 0.00784192141f, 0.00737335905f, + -0.00259011192f, 0.0181177687f, -0.0132434117f, 0.018963784f, 0.0191199724f, + 0.026330635f, 0.00948189199f, -0.0222437251f, 0.0186383929f, -0.0146686239f, + 0.0261874627f, -0.0131457942f, -0.0288426541f, 0.00606203312f, 0.0220354758f, + 0.030821031f, 0.0171025489f, -0.000254618411f, 0.0259792134f, 0.00738637429f, + -0.00699590519f, 0.0184952207f, -0.00101766014f, 0.0154886087f, -0.0235713199f, + 0.015254328f, -0.0184691902f, 0.0235973522f, 0.0120524811f, 0.0075685936f, + -0.00657940516f, -0.00598719344f, -0.00545680616f, 0.0303784981f, 0.0083104847f, + 0.0107509168f, 0.0210462864f, -0.0187034719f, -0.0154105155f, 0.0154625773f, + -0.0142000606f, 0.00298058102f, -0.00786144566f, -0.000340847007f, 0.0101131508f, + 0.0218923036f, 0.0115643945f, 0.00894825067f, -0.0400361009f, -0.00469864532f, + 0.017688252f, 0.0132759502f, -0.000626377587f, 0.00133328943f, -0.02691634f, + 0.0118897855f, -0.0139397485f, 0.0160222501f, -0.00991140865f, -0.00740589807f, + 0.0139397485f, 0.0202523321f, -0.0136664193f, 0.0135753099f, -0.000461241667f, + 0.0136013413f, 0.00942332204f, -0.0366260037f, 0.0269684009f, -0.0307169054f, + 0.0225691162f, -0.00915650092f, 0.000590991287f, 0.0160222501f, -0.0324089378f, + 0.00984632969f, 0.00721066352f, 0.0285042468f, 0.0105947293f, -0.00898729824f, + -0.00730177294f, 0.00969014224f, 5.5163935E-05f, 0.0160092339f, -0.0175190493f, + -0.000647121225f, 0.000599939551f, -0.00299034291f, -0.0259922296f, -0.00557069294f, + 0.00654686568f, 0.0132564269f, 0.00277558481f, 0.00223706267f, -0.00996997859f, + -0.00168389815f, 0.000423414982f, 0.0263566673f, -0.00315141142f, 0.0128399264f, + -0.0270204637f, 0.0207339115f, 0.0210723169f, 0.00427238317f, -0.0255887434f, + -0.00433420762f, 0.00857730582f, -0.00201742398f, 0.02998803f, -0.0162435155f, + 0.0163736716f, -0.000488086429f, -0.00613687327f, -0.0131718256f, -0.00406738697f, + 0.0132108722f, -0.0353244394f, 0.0208120048f, -0.0351682529f, 0.0164127201f, + 0.00179941196f, 0.000271294703f, -0.0177272987f, 0.0240138527f, 0.019354254f, + -3.47253153E-05f, -0.00664773723f, 0.017493017f, 0.0115448711f, -0.0162695479f, + -0.00602298649f, -0.0129375439f, 0.000931431598f, -0.00546656782f, -0.0188075975f, + 0.00327505986f, -0.0097031584f, 0.0387605689f, 0.00172131811f, 0.00888317265f, + -0.016725095f, -0.0359752215f, -0.00115432439f, 0.116515987f, 0.0298839044f, + 0.00661519775f, -0.00137721724f, 0.0113951908f, -0.013523248f, -0.0121240662f, + -0.0302223116f, 0.00444484036f, -0.00966411084f, 0.0395154767f, -0.0385523178f, + 0.000324780849f, 0.00974871311f, 0.01479878f, -0.000246076903f, -0.00403159391f, + -0.0144083109f, 0.00834302418f, -0.0322787836f, 0.00188726746f, 0.0247687586f, + 0.0222046785f, -0.0180917364f, -0.00803715643f, 0.0132303955f, 0.0162695479f, + -0.00588632235f, -0.0130156381f, -0.0233630706f, -0.02691634f, 0.00324740168f, + -0.00186937104f, 0.00115269748f, -0.00608481094f, -0.001112837f, 0.00422357442f, + -0.0066770222f, 0.0235322732f, -0.00516395411f, 0.0131327789f, -0.0152673433f, + 0.00222730101f, -0.00577243557f, 0.0236624293f, -0.00526482565f, -0.0139397485f, + 0.0169463605f, 0.00142033154f, -0.0196275823f, 0.0409211665f, 0.0137445135f, + -0.007080507f, -0.0099179158f, -0.00090051943f, 0.00773779675f, 0.0070674913f, + -0.0152282966f, 0.0120589882f, 0.0392030999f, -0.008648891f, -0.0233110078f, + 0.0118767694f, -0.012625169f, 0.0267601516f, -0.0271245893f, -0.0244563837f, + -0.0102823535f, -0.0180917364f, -0.0127423098f, 0.0215018336f, -0.0128204031f, + -0.0092150718f, 0.00549259922f, 0.0256538223f, -0.00379080442f, 0.0114016989f, + -0.0139787951f, 0.00255757291f, -0.00619544368f, -0.0057984665f, -0.0197837688f, + -0.0235062428f, -0.0176752359f, -0.0242351182f, 0.0011697805f, 0.00394373806f, + -0.0158530474f, -0.00893523544f, -0.0166470017f, 0.0248989146f, 0.00281788572f, + -0.00421055872f, -0.00837556273f, -0.00841461029f, -0.0223218184f, 0.00124055299f, + 0.000373996212f, 0.00523554021f, 0.0186904557f, 0.00403484795f, -0.0325651243f, + -0.0289728101f, 0.00958601758f, 0.0107899634f, -0.0265779328f, -0.00157895952f, + 0.0209681932f, -0.0158400312f, -0.000473850552f, -0.00565529475f, -0.0202263016f, + -0.00179615803f, 0.00473118434f, -0.00955998618f, 0.0131653175f, 0.0202002693f, + 0.030951187f, 0.00206135167f, -0.00724971015f, -0.00179453113f, -0.0115709025f, + 0.028322028f, 0.0272026826f, -0.0178574547f, -0.010445049f, 0.0239748042f, + -0.0325651243f, 0.00483530946f, -0.00596441608f, -0.00314815738f, 0.021150412f, + 0.00686574914f, -0.0188856907f, -0.0185472835f, -0.000634919095f, -0.0210853331f, + -0.000795580854f, -0.017493017f, -0.0268642772f, -0.00907840766f, -0.00798509363f, + -0.0119353402f, -0.00383961317f, 0.00131051207f, -0.0283740908f, 0.00342962053f, + 0.0111804325f, -0.0165428761f, 0.00388842192f, -0.00637115492f, -0.0146035459f, + -0.0401141942f, -0.00697638188f, -0.00222730101f, -0.0247947909f, -0.0100545799f, + -0.0100415647f, 0.0191329885f, 0.0198228173f, 0.0193672683f, -0.0138356229f, + 0.0369644128f, 0.0108094877f, -0.00245832861f, 0.0222827718f, -0.00870746188f, + -0.00368993334f, -0.0408691019f, 0.0410773531f, 0.0261484161f, 0.0162695479f, + 0.0139397485f, -0.0124429502f, 0.0109851984f, 0.0196536127f, 0.0264217444f, + 0.00763367163f, -0.0203564577f, -0.0235192571f, -0.0147076705f, -0.000723588106f, + -0.00363136292f, -0.00323438598f, -0.0059709237f, -0.0271766521f, 0.0105361585f, + 0.00810223445f, -0.0184431598f, 0.0113886828f, 0.00793953892f, -0.00196536141f, + -0.00281300466f, 0.00382334366f, -0.000423008227f, -0.0174149238f, -0.00147158059f, + 0.00115432439f, 0.0279836208f, 0.00866190717f, -0.00345565192f, 0.0171415955f, + -0.0314457826f, -0.0207729582f, 0.00995045528f, 0.0381878801f, 0.00338731986f, + -0.0160743129f, 0.0233370382f, -0.011596933f, -0.0122216837f, -0.0196796451f, + -0.0231548194f, -0.0401662588f, 0.00157326518f, -0.0079981098f, -0.00435373094f, + -0.00299359672f, -0.0154365469f, -0.0200180504f, 0.0183650646f, -0.00445460202f, + 0.0156578124f, -0.00491340319f, 0.0179095175f, 0.0165168438f, -0.00598393939f, + -0.00774430437f, 0.024287181f, 0.01652986f, 0.00427889079f, 0.0181568153f, + 0.0222567413f, 0.00942332204f, -0.00238836952f, -0.0233500544f, -0.0125861214f, + -0.0251331963f, -0.0136664193f, 0.0279575903f, -0.00236721919f, 0.0160612967f, + -0.0143172015f, -0.006472026f, 0.00640694797f, 0.00807620306f, -0.012683739f, + 0.0138095915f, -0.0115774097f, -0.0340489075f, -0.0341270007f, -0.00457174284f, + -0.0126642156f, -5.41470872E-05f, 0.0134321386f, -0.00793953892f, -0.010633776f, + -0.0122412071f, -0.0169984233f, -0.00913046952f, 0.00357930036f, 0.0213065986f, + 0.0028455439f, -0.00290899514f, -0.0124234259f, -0.0107704401f, 0.00458475854f, + -0.00834302418f, -0.000212317595f, 0.027046496f, -0.01345817f, -0.00721066352f, + 0.0035825544f, -0.00811525062f, -0.00842111744f, 0.0281918719f, -0.00339382747f, + -0.0421966985f, 0.0118637541f, -0.00546331378f, -0.00144066836f, -0.000986748026f, + -0.00642647129f, 0.0124559654f, -0.0224780068f, -0.00389167573f, -0.0152413119f, + -0.00368993334f, 0.0130026219f, -0.0146425925f, -0.0145905297f, -0.0300400928f, + 0.00825842191f, 0.00647528004f, 0.00664448319f, -0.0223868974f, 0.00427563721f, + 0.0180136431f, -0.0342311263f, 0.0328514688f, -0.0122151766f, 0.0209031142f, + -0.0213846937f, 0.0283480585f, -0.0136013413f, 0.00619544368f, 0.0248338375f, + -0.0279055275f, -0.00638091657f, -0.0128984973f, -0.0169333443f, 0.00307494448f, + 0.00939078256f, -0.0152933747f, 0.0138095915f, -0.0103474325f, 0.00507935276f, + -0.0170765165f, 0.0039860392f, 0.0178053919f, -0.00683320966f, -0.00489713391f, + 0.0234151334f, 0.000928991125f, 0.000820391928f, -0.00213781861f, 0.00889618881f, + 0.00739288237f, -0.0274109337f, -0.0170635004f, -0.0186774395f, 0.0232459288f, + 0.00754906982f, -0.00512165343f, -0.00323764002f, -0.00604576385f, 0.000810223457f, + 0.0344393775f, -0.00222242018f, 0.000545029819f, 0.0152152805f, 0.0410513207f, + -0.00913697761f, 0.0131002394f, 0.0179095175f, -0.0233110078f, 0.00577568915f, + -0.0286083724f, -0.0376932882f, -0.0209161304f, -0.017493017f, 0.0452163257f, + 0.0198748782f, -0.00881158654f, -0.0121566057f, 0.0161133595f, -0.0499800481f, + -0.00598068582f, -0.0218662713f, 0.0202523321f, 0.0329555944f, -0.012306286f, + 0.00251852605f, 0.0291810594f, 0.0153974993f, -0.00311887218f, -0.0165949389f, + 0.00566505641f, -0.00134549162f, -0.0130937314f, 0.00762716401f, 0.000191167186f, + -0.00354350731f, -0.00959252473f, -0.00950792339f, 0.0220484901f, -0.0172066726f, + 0.0168422349f, -0.00137559022f, -0.00399254682f, 0.00636464683f, -0.00257058837f, + 0.0169593766f, -0.00252015283f, -0.00619869772f, -0.020629786f, 0.0182869714f, + 0.00174572237f, 0.018521253f, -0.0266039632f, 0.01479878f, -0.00355001516f, + -0.00774430437f, -0.0115383631f, -0.000981053687f, -0.0188987069f, -0.0246776491f, + 0.012429934f, 0.0275671203f, 0.0107183782f, 0.00236396515f, 0.0114277303f, + 0.0102302916f, -0.0194974262f, -0.0132499197f, 0.0206558164f, -0.00516720815f, + -0.0104906037f, 0.00215896894f, -0.0150330616f, 0.00474420004f, 0.00260312762f, + 0.0247687586f, -0.01300913f, 0.000319899962f, -0.00514117675f, 0.00389492954f, + -0.00315466523f, 0.0117661366f, 0.0165689066f, 0.00163020869f, 0.0140568893f, + -0.00847318023f, 0.00154398009f, -0.00359882391f, -0.0122021604f, 0.00495245028f, + -0.00246809027f, -0.00824540667f, -0.0225170534f, 0.00501752831f, -0.0120264497f, + 0.00063735951f, -0.0209942237f, -0.00678765494f, 0.0261744484f, 0.234073237f, + -0.00612385757f, -0.000167983075f, 0.0171155632f, -0.0101847369f, 0.0157619379f, + 0.016464781f, 0.000291224889f, 0.017558096f, 0.00316442689f, 0.021150412f, + 0.0108094877f, 0.00695685856f, -0.00198651175f, 0.00566505641f, -0.0169854071f, + -0.0177793615f, -0.00226472109f, -0.00543728285f, -0.0253154151f, 0.0101587055f, + 0.0146295773f, -0.000383147853f, -0.01127805f, 0.0314718112f, 0.0127553251f, + -0.0128269112f, -0.000238145498f, 0.0466740765f, 0.00820636004f, -0.00457825046f, + -0.012306286f, 0.0100415647f, -0.0298578739f, -0.00331736077f, -0.00252015283f, + -0.00245507481f, -0.0187945813f, -0.0157489218f, 0.000808189739f, 0.0192110818f, + 0.0147337019f, -0.0092150718f, -0.0170895327f, 0.00566831045f, 0.0158790778f, + -0.00857730582f, 0.0303784981f, -0.0186774395f, -0.00434396928f, -0.0276712459f, + -0.0166860484f, 0.0289728101f, 0.0194323473f, -0.00884412602f, 0.00993743911f, + 0.010510128f, 0.00510213012f, 0.00331247994f, -0.0139397485f, 0.0121696219f, + 0.0144994203f, -0.000254008308f, -0.00571386516f, -0.0158140007f, 0.0206948649f, + -0.0162825622f, 0.0115448711f, 0.0103279082f, -0.0200440828f, -0.0113561442f, + -0.028712498f, -0.0208380371f, -0.00805667974f, 0.000531200727f, -0.0124039026f, + 0.032226719f, 0.00439277757f, 0.00892222021f, 0.0189898163f, 0.0104906037f, + 0.00428865291f, -0.00151388138f, 0.0107834563f, -0.0234932266f, -0.0114993164f, + 0.0229856167f, 0.00900031347f, -0.0109917065f, -0.0197186917f, -0.00984632969f, + -0.0232068822f, 0.00504030567f, -0.000213131076f, 0.0169723909f, 0.0139397485f, + 0.0221656319f, 0.0217751618f, 0.00188075972f, -0.0354025364f, -0.0180396736f, + 0.000664610998f, 0.0331378132f, -0.00781589095f, -0.0231548194f, -0.0178053919f, + 0.0228424445f, 0.0134842005f, 0.00219964283f, -0.0184431598f, -0.0202132855f, + -0.0250030402f, 0.00448063342f, -0.0111088473f, 0.0117791519f, 0.00297732721f, + 0.0112064639f, 0.00127471902f, 0.0098918844f, -0.0132434117f, 0.00479626236f, + -0.00739288237f, -0.00389167573f, 0.00917602517f, 0.0187815651f, -0.0270204637f, + -0.0344393775f, 0.00785493758f, 0.0143041862f, -0.0244563837f, 0.0212415215f, + -0.027046496f, -0.000732536369f, -0.00948840007f, -0.020187255f, 0.00249737548f, + 0.00102172757f, -0.0114863003f, 0.00014185012f, 0.00623449078f, 0.0147597333f, + -0.0067160693f, 0.013965779f, 0.0226472095f, 0.0125861214f, -0.00465634465f, + 0.000698777032f, 0.0133670596f, -0.0251852591f, -0.020955177f, -0.00764668733f, + -0.019796785f, -0.00953395478f, 0.00854476634f, -0.00599370105f, -0.0365479104f, + -0.020759942f, -0.0193282217f, -0.0117075667f, 0.0154235307f, -0.0282699652f, + 0.0275410898f, 0.00465634465f, -0.0258620717f, -0.00124380691f, -0.025823025f, + -0.166600168f, 0.0152152805f, 0.0332419388f, -0.0162565317f, 0.0223999135f, + -0.0238186177f, 0.0508911423f, 0.0106467921f, -0.01999202f, 0.00883110985f, + 0.0167381112f, -0.00905237626f, -0.0204605833f, -0.00997648668f, -0.00332712242f, + 0.0122281918f, 0.00875952467f, 0.0207859743f, 0.00242090854f, 0.0128464345f, + 0.00754906982f, -0.015957173f, -0.00578870485f, 0.012878974f, 0.00515744649f, + 0.00547632948f, 0.0134842005f, 0.0132238884f, 0.0131523022f, -0.00382659747f, + -0.022425944f, -0.0274369642f, 0.0108550424f, 0.0209291466f, 0.0103734639f, + 0.00857730582f, -0.00344589003f, 0.00293014548f, -0.0255496968f, -0.0037712811f, + 0.00650131097f, 0.0333981253f, 0.0265779328f, 0.00536244269f, 0.0180917364f, + 0.0468823276f, 0.0292591546f, 0.011343128f, 0.0103474325f, 0.00274792663f, + 0.0194583777f, -0.032174658f, 0.00749049941f, -0.000413043133f, 0.0424309783f, + 0.0206558164f, 0.00330597209f, -0.00317256176f, 0.0129310358f, -0.00294804201f, + -0.0165949389f, 0.00374524971f, 0.00758811692f, -0.0138226077f, -0.0144994203f, + -0.0253024008f, 0.000335559424f, 0.0101391822f, -0.0239487737f, 0.00305704796f, + -0.0200050361f, 0.00252503366f, -0.00911094621f, -0.0260312762f, 0.022230709f, + 0.00961855613f, -0.0152803585f, 0.00847318023f, 0.00253479555f, -0.0046205516f, + -0.000312375312f, 0.00871396996f, -0.00551212253f, -0.00750351511f, 0.0186383929f, + 0.010829011f, 0.00307819829f, 0.00278371945f, -0.00345565192f, -0.0546136163f, + -0.00588306831f, -0.0064459946f, -0.0183780808f, -0.011212972f, -0.00600997079f, + 0.0162044689f, 0.028322028f, -8.69403957E-05f, 0.00965760369f, -0.0202913787f, + 0.00476372335f, -0.00575616583f, -0.0313676856f, 0.0122021604f, 0.0115448711f, + 0.0453464836f, 0.0181568153f, 0.0155146401f, 0.00256245374f, -0.0108680576f, + -0.0162044689f, 0.00934522785f, 0.000158831463f, 0.0278534647f, -0.0266820583f, + 0.00742542138f, -0.00663146749f, -0.0287385285f, 0.00566505641f, -0.00637440849f, + 0.0695555657f, 0.00155130133f, -0.0310032498f, 0.00732129626f, 0.00987236109f, + -0.0212154891f, -0.104020976f, -0.00687225675f, 0.0161654223f, 0.0283480585f, + -0.00815429725f, 0.0259141345f, -0.0103734639f, 0.025823025f, -0.0128138959f, + 0.0267601516f, 0.00435698498f, -0.0477153286f, -0.00474745408f, -0.0108159948f, + 0.00777033577f, 0.00395350019f, 0.00575291179f, -0.00109412707f, -0.0186123624f, + 0.02691634f, -0.0179095175f, 0.0132564269f, 0.00136826898f, -0.000920856372f, + -0.0109917065f, 0.00587005261f, -0.0198358316f, 0.00164973212f, -0.00225821324f, + 0.00935173593f, 0.00848619547f, -0.0109266276f, 0.0349600017f, 0.00245670159f, + 0.0103929872f, -0.000142765275f, 0.001906791f, 0.001313766f, 0.0320445001f, + -0.0336063765f, -0.00107460364f, -0.00214432646f, 0.0100480728f, -0.0425871685f, + -0.018391097f, -3.13951423E-05f, -0.00428865291f, 0.000374606316f, 0.0353504717f, + -0.0313156247f, -0.0212935843f, -0.00811525062f, -0.0119223241f, -0.0155797182f, + 0.0276712459f, 0.00702193659f, 0.00162451435f, -0.0121566057f, -0.00890920404f, + 0.0213326309f, -0.00335478061f, -0.0205516927f, -0.00351096829f, -0.00362810912f, + 0.00466285227f, -0.00983982254f, -0.0191199724f, -0.0060555255f, 0.00866841525f, + -0.0284521841f, -0.00784192141f, 0.00753605412f, -0.0195755195f, 0.0200180504f, + -0.0316280015f, -0.00063451234f, -0.012176129f, -0.0176231731f, 0.0181568153f, + -0.0138876857f, -0.00545355212f, -0.0184301436f, 0.0218272246f, -0.0217100848f, + -0.00123485865f, 0.00635163113f, -0.0143822795f, 0.0216059592f, 0.00308307912f, + -0.0129245287f, 0.00404460961f, 0.00895475876f, 0.0054470445f, -0.0160222501f, + -0.0046335673f, 0.0127032623f, 0.0114537617f, -0.0172457211f, 0.000672745809f, + 0.0144083109f, -0.0203434415f, 0.00331247994f, -0.0519323945f, 0.0225170534f, + -0.00890269596f, 0.012176129f, 0.00105182629f, -0.0141479988f, -0.00577243557f, + -0.0180787202f, 0.00189540221f, 0.0117075667f, 0.00970966555f, 0.00596116204f, + 0.0134061072f, -0.0146556087f, -0.00777684385f, -0.001112837f, 0.0198098011f, + 0.000662577339f, 0.00283090118f, 0.0137835601f, -0.0259401668f, -0.00139918108f, + -0.00655662781f, -0.0186774395f, -0.00977474451f, -0.00935824402f, -0.00254943804f, + 0.0334241576f, -0.00724971015f, -0.0178314243f, 0.00481903972f, -0.0211894587f, + 0.0158009846f, -0.00333200325f, 0.0261353999f, -0.0302483421f, 0.00137070939f, + 0.00756208552f, 0.0238576643f, 0.0529476143f, -0.0151502024f, -0.0145384679f, + 0.0168812815f, -0.0201742388f, -0.00393723045f, -0.00830397662f, -0.027489027f, + -0.00797858648f, 0.0262915883f, 0.00484832516f, 0.0113301128f, 0.0136924507f, + -0.0228814911f, -0.0139787951f, -0.00909793098f, -0.020955177f, 0.0352723785f, + -0.00452618813f, -0.00104369142f, -0.0241830554f, 0.0274629965f, -0.0152022652f, + -0.00590584567f, 0.00184171274f, 0.0118637541f, 0.00303589762f, -0.0197186917f, + 0.0200050361f, 0.00268122135f, -0.0210853331f, 0.000183845885f, -0.0135883261f, + 0.0035272378f, 0.0103214011f, -0.0182218924f, 0.0246776491f, 0.0298058111f, + 0.0206558164f, -0.0238967109f, 0.000355692988f, 0.00565529475f, 0.0113170976f, + -0.0120329568f, 0.00206460548f, 0.037927568f, 0.0278274342f, -0.0172717515f, + 0.0221656319f, 0.0230116472f, 0.000263363298f, -0.00160092348f, 0.0185733158f, + -0.0116555039f, -0.0115383631f, 0.00619218964f, 0.0371205993f, -0.027046496f, + -0.0156317819f, 0.0117010586f, 0.047220733f, -0.00151632179f, -0.0161393918f, + -0.0245344769f, -0.00862936769f, 0.0020662325f, 0.0138746696f, 0.00733431196f, + -0.0284001213f, -0.00239162357f, 0.00951443147f, 0.0216450058f, -0.013965779f, + 0.00611734996f, 0.0203304272f, -0.0112259872f, 0.0130677f, -0.00206785952f, + -0.0409211665f, -0.00559672434f, 0.0382920057f, 0.00742542138f, -0.0016033639f, + 0.0123453327f, -0.00834953133f, -0.00284066307f, 0.0145775145f, 0.0074579604f, + -0.0287905913f, -0.0281918719f, -0.0216840524f, -0.00473118434f, 0.00115920522f, + -0.00817382056f, 0.000505169446f, -0.0087985713f, -0.0187555347f, -0.0182739552f, + 0.0123193013f, -0.0320965648f, 0.0252893846f, 0.0139267324f, 0.00260638143f, + 0.0168162044f, -0.0135102319f, 0.0246255863f, -0.0200570971f, 0.0180526897f, + -0.0180657059f, -0.030118186f, 0.0183650646f, -0.00930618122f, -0.00181080063f, + -0.0178184081f, -0.00331573375f, 0.0235062428f, 0.00162532774f, 0.0211243797f, + 0.00374524971f, -0.0167771578f, 0.0160743129f, 0.0173107982f, 0.0136273727f, + 4.12585541E-05f, -0.01172709f, -0.00291062193f, 0.0186904557f, 0.0303784981f, + -0.000156187656f, -0.0430557318f, -0.00409667194f, -0.00752954651f, -0.0157879684f, + -0.0150460778f, 0.00242253556f, -0.0236103665f, 0.0113236047f, -0.00201905076f, + -0.0133800758f, 0.0136664193f, -0.0331898779f, 0.015892094f, -0.0114928083f, + -0.0353244394f, 0.014226092f, 0.0164777972f, -0.0294153411f, -0.00834953133f, + -7.23486446E-05f + ] + } + }, + new MovieWithPlot + { + Title = @"The Charge of the Light Brigade", + Year = 1936, + Available = true, + Plot = new NestedPlot + { + Plot = + @"A major countermands orders and attacks to revenge a previous massacre of men, women and children.", + Rating = 4, + PlotEmbedding = + [ + -0.0329607055f, -0.0246873293f, -0.018857453f, -0.00159607758f, -0.00163923728f, + 0.00919632893f, -0.0200526435f, -0.0178747419f, 0.0219118297f, -0.0105110388f, + 0.0259489194f, 0.0255372413f, -0.00599255366f, -0.0202252828f, 0.0161616355f, + -0.00659346906f, 0.0321639106f, -0.00854561385f, 0.00182266592f, -0.0170381069f, + 0.00623491174f, 0.0336778201f, 0.00853897352f, -0.015391401f, 0.00287509779f, + 0.0174232256f, -0.00105741178f, -0.0365993977f, 0.0219118297f, -0.00752970157f, + -0.00838625524f, -0.0141430907f, 0.0111418338f, -0.00401384896f, -0.0456828438f, + -0.00699850591f, -0.00693210633f, -0.035138607f, -0.0120249465f, -0.0143954083f, + 0.0249396469f, 0.0187246539f, 0.0130474987f, -0.00254808017f, -0.0327482261f, + -0.0298266485f, 0.0151789226f, -0.00161350751f, -0.0247935671f, 0.00802105758f, + 0.0171177872f, 0.025497403f, -0.0158030782f, -0.000277010346f, 0.00375821092f, + -0.0138907721f, -0.00198534457f, 0.00968104508f, -0.00380801037f, -0.00334653398f, + -0.00431264658f, -0.00396404928f, -0.0186980944f, -0.00292987726f, 0.0282596201f, + -0.00361877191f, -0.0270245895f, -0.00453840476f, -0.0221375879f, -0.00841945503f, + 0.0374227501f, 0.031021839f, -0.00756954122f, -0.0137048541f, 0.0243951716f, + -0.0281002615f, -0.0208095983f, -0.0129213398f, 0.015391401f, -0.0116863092f, + 0.0317920744f, -0.0221110284f, -0.0115070306f, 0.00827337615f, 0.0276753046f, + -0.00588299427f, 0.00184424571f, 0.0134458961f, -0.0151258027f, -0.00591619406f, + -0.0127287814f, 0.00393416965f, 0.0120647866f, 0.0146610066f, -0.0221508685f, + 0.00187080551f, -0.0215798318f, 0.025497403f, -0.00239868136f, -0.0155507596f, + -0.000952002592f, -0.00182432588f, 0.00036415967f, -0.00706490502f, -0.0218188707f, + -0.00417320756f, -0.00522231963f, -0.0103383996f, 0.010643837f, 0.00950840581f, + -0.027276909f, 0.00972088426f, 0.00276719849f, -0.0619374402f, 0.00929592829f, + -0.0240764525f, 0.0176622625f, -0.00414332794f, 0.00458156457f, -0.0122971842f, + 0.0368384346f, 0.0150062833f, 0.0108363964f, -0.00598591333f, 0.0273034684f, + -0.0117527088f, 0.00549455732f, -0.0192824099f, -0.0207830388f, -0.00164587726f, + 0.03237639f, 0.0269714706f, 0.00533519872f, -0.000216005821f, 0.00595603371f, + 0.0275425054f, -0.0158030782f, 0.0184988957f, -0.00823353603f, -0.00971424486f, + 0.0128748603f, 0.0228547025f, -0.0237710159f, -0.0147805251f, -0.00475088321f, + -0.00412672805f, -0.00992008299f, 0.0200128052f, 0.0124167036f, 0.00289833755f, + 0.0117726289f, -0.0242756512f, 0.00572363567f, -0.0244748499f, 0.0277284253f, + -0.00963456556f, -0.00384453009f, 0.0142493295f, -0.00675282767f, -0.0227617435f, + 0.0133462967f, 0.0100661619f, 0.0139837312f, 0.00598259363f, 0.0315530337f, + 0.0216860715f, 0.0100528821f, 0.0227086246f, 0.00318717537f, -0.0230007824f, + 0.00793473888f, 0.0174232256f, -0.0314733572f, 0.00603903318f, -0.0176755432f, + 0.019933125f, 0.012609262f, 0.0109891146f, -0.0253911633f, 0.0156437177f, + -0.0300125666f, 0.00310085597f, 0.0158694778f, 0.0294813719f, -0.0366525166f, + -0.00306267617f, 0.00194218499f, -0.00492020184f, 0.00354241254f, -0.0116863092f, + 0.0273300279f, 0.0153250014f, 0.00150145835f, -0.0116398297f, -0.662507474f, + -0.00483056251f, -0.0130142989f, 0.00731722312f, 0.0309155993f, -0.0056240363f, + 0.000952832634f, -0.00241528125f, 0.00496668136f, 0.00299627683f, 0.00120930059f, + 0.0178614613f, -0.00139521912f, -0.0322967097f, -0.0186582562f, -0.0227219034f, + -0.0148734841f, 0.00153465813f, 0.0191628914f, 0.00692546647f, -0.0104180789f, + 0.0350058079f, 0.00233560195f, 0.00208494393f, 0.000625400164f, 0.00294979708f, + 0.0173169859f, 0.00512272026f, -0.0110023944f, -0.0118589476f, -0.00615191227f, + 0.00842609443f, -0.00593611412f, 0.0267855525f, 0.0558286868f, -0.0118257478f, + -0.0212611146f, 0.0191097725f, 0.0100661619f, 0.0320842303f, -0.0161483549f, + -0.00554767717f, 0.0216462314f, -0.0142891696f, 0.00837961491f, -0.0202784035f, + 0.02844554f, -0.0192558505f, -0.000318925013f, -0.00802769791f, 0.00715786451f, + 0.00816713646f, -0.00343617331f, 0.00770898024f, 0.00790817849f, 0.013054139f, + 0.031871751f, -0.00922952872f, -0.00446204515f, -0.0144352484f, -0.00630463101f, + 0.0101724006f, 0.00809409749f, -0.0133396564f, -0.0175161846f, -0.00178448611f, + -0.000200339695f, 0.0460812412f, 0.0176224224f, -0.0238905344f, 0.016281154f, + -0.00121096056f, -0.0229476616f, -0.00285019795f, -0.00865849294f, 0.00255970005f, + 0.0230804607f, -0.00506296055f, -0.000187474798f, -0.00351585262f, -0.0035490524f, + -0.0264004357f, -0.0373961888f, 0.0116531095f, 0.0378477052f, -0.00865185261f, + -0.0215001535f, -0.00796129834f, 0.0197604876f, 0.00161516748f, -0.00483388267f, + 0.00134126958f, -0.0114539107f, -0.00755626149f, 0.00737034297f, 0.0295079313f, + -0.00828001555f, -0.00434916606f, 0.0045948443f, -0.0258957986f, 0.00978728384f, + -0.00321871508f, -0.0118124681f, -0.00614195224f, -0.00457492471f, -0.00468116347f, + -0.0239303745f, 0.00272071897f, 0.0342886932f, -0.0107633565f, 0.00423628697f, + 0.00576347532f, -0.0124432631f, 0.00213806331f, 0.00920296833f, -0.0218587108f, + 0.0166397113f, -0.00167658704f, 0.0236116573f, -0.0271042697f, -0.00540823815f, + 0.00370841124f, 0.00661670882f, -0.0149000445f, 0.025590362f, 0.030782802f, + 0.0166662708f, 0.00230074208f, 0.00998648256f, -0.00276719849f, -5.31714613E-05f, + -0.000995992217f, 0.0191230513f, 0.00942208711f, 0.0190300923f, 0.01412981f, + 0.0197604876f, -0.010550878f, 0.019229291f, 0.00835305545f, -0.00587635441f, + 0.0130474987f, 0.0118257478f, 0.00525883911f, 0.00352249271f, -0.0234257374f, + -0.0245412495f, -0.00723090395f, -0.0595470592f, 0.0287908167f, 0.018525457f, + 0.000966112479f, -0.0189636927f, -0.0249396469f, -0.00766250072f, 0.00865849294f, + -0.0291360933f, -0.010530958f, 0.00376153085f, -0.01932225f, 0.0152586019f, + 0.0225625448f, -0.00917640887f, 0.00880457181f, 0.00513599999f, -0.0102587203f, + 0.0228945427f, 0.00439232588f, 0.00181270589f, -0.0205174405f, 0.00790153909f, + -0.0221375879f, 0.000317472528f, 0.0104711987f, -0.0114207109f, -0.00400056876f, + -0.0337840579f, -0.00106820173f, -0.00555099687f, 0.0217923112f, 0.0115468707f, + -0.00472764345f, -0.0134724556f, 0.0118788676f, 0.00477744313f, 0.0380070657f, + 0.00471768342f, 0.0114207109f, 0.00899048988f, 0.0223367866f, 0.00869169272f, + 0.00616851216f, -0.000866513292f, -0.0132334176f, 0.00677606743f, -0.0050198012f, + 0.00570371561f, 0.00187744538f, 0.0209955163f, 0.0373961888f, 0.0291626547f, + -0.000258543005f, 0.0214204732f, 0.00384121016f, -0.000275557861f, -0.0432924628f, + 0.00559415668f, -0.0300125666f, 0.0502245687f, 0.00601579342f, 0.0160553958f, + -0.015112523f, -0.0123901442f, -0.0194683298f, -0.011699589f, 0.0322967097f, + 0.0102985604f, 0.00270577893f, 0.0144618079f, -0.00515259989f, -0.0124764629f, + -0.0241826922f, 0.0193488095f, -0.00826009549f, -0.0479935482f, -0.013127178f, + 0.0124631831f, 0.00678270729f, 0.0124100633f, 0.000304400135f, 0.00514596002f, + 0.0234655775f, -0.0200924836f, 0.0314202346f, 0.016892029f, -0.00617515203f, + -0.00471436325f, -0.00117527088f, 0.012257345f, -0.000128234009f, -0.0231070202f, + 0.0274362676f, -0.00514264032f, -0.024753727f, -0.00298133679f, -0.0183660984f, + 0.0289236158f, 0.00776873995f, -0.0185785759f, 0.0183793772f, -0.00215964322f, + -0.000189238533f, 0.00240864139f, -0.00541487802f, -0.000102089209f, -0.0246873293f, + 0.0242756512f, -0.00517251994f, 0.0274097081f, 0.0250857249f, -0.000887263101f, + -0.0196808074f, 0.0138376523f, 0.00308093615f, 0.0158960372f, 0.00401384896f, + 0.01806066f, 0.0133994156f, -0.0120913461f, -0.0120315868f, -0.00126574014f, + 0.0119983871f, 0.0156038785f, -0.0167990699f, 0.00709146494f, -0.0123038245f, + -0.00249662064f, 0.00691882614f, 0.0019571248f, 0.00228746235f, -0.00237876154f, + -0.0292157736f, 0.0271042697f, 0.0102321608f, -0.00639095064f, -0.0024717208f, + -0.0137845334f, 0.00308425608f, -0.0243553314f, 0.0244615711f, 0.0116066299f, + 0.0190699324f, -0.0153250014f, -0.0106969569f, -0.0206103995f, -0.0150461234f, + 0.0254442822f, -0.0250724461f, 0.00485380227f, -0.0178349018f, 0.0100064026f, + 0.00608219299f, -0.00266261934f, -0.0204643216f, 0.0127686206f, 0.0180872194f, + 0.00740354275f, -0.0194152091f, -0.0208494384f, -0.0150859626f, 0.00840617437f, + 0.0141032506f, 0.00736370264f, -0.0104114395f, 0.00162927737f, 0.00807417743f, + -0.0194550492f, -0.0189769734f, 0.01932225f, 0.00924280845f, 0.00859873369f, + -0.0152718816f, -0.00693210633f, 0.000851573364f, 0.116863094f, 0.0383789018f, + -0.0210884772f, -0.00605895277f, -0.0188441742f, 0.0142626092f, -0.021008797f, + -0.00882449187f, -0.00583651476f, -0.0275425054f, -0.012423344f, 0.000378892059f, + 0.00940216705f, 0.0113144722f, 0.0259489194f, 0.01412981f, 0.0065901489f, + -0.00812729727f, -0.0162944328f, -0.00734378304f, 0.0146875661f, 0.00339965359f, + 0.0212743953f, 0.0150859626f, -0.0121577457f, -0.0229078215f, 0.000607555266f, + 0.0166131519f, -0.00984704401f, -0.0217923112f, -0.0328544639f, 0.00464796415f, + -0.00858545303f, 0.021101756f, 0.00589959417f, 0.0114539107f, 0.0286048986f, + -0.023346059f, 0.0109824752f, -0.0135056553f, 0.0252450835f, -0.00724418368f, + -0.00729066366f, -0.00990680326f, 0.00248998078f, -0.0147274053f, -0.0254310034f, + 0.00171476672f, -0.00985368341f, -0.0296938494f, 0.0166662708f, -0.0256965999f, + -0.0460015647f, -0.0148203652f, -0.00847921427f, 0.00632787077f, 0.00563067617f, + 0.0380867459f, -0.010179041f, 0.0385382622f, -0.022270387f, -0.0185652953f, + -0.0109891146f, -0.0188707337f, 0.0162545945f, -0.014647726f, -0.0124565437f, + -0.00287509779f, -0.0202518422f, -0.00561407628f, -0.013240057f, -0.0237046164f, + -0.0104114395f, 0.00758282095f, -0.006165192f, 0.0200128052f, 0.0156304389f, + -0.0301453657f, 0.0179544203f, 0.0206103995f, -0.019840166f, -0.0220313482f, + -0.00776873995f, -0.0241694134f, 0.00755626149f, 0.00452844473f, 0.0105043985f, + -0.0174365044f, -0.0248068478f, 0.0241295733f, 0.0111750336f, 0.0039142496f, + 0.0147938048f, 0.00678934716f, -0.017263867f, 0.0028103583f, -0.00505632069f, + 0.0263074767f, 0.000700099568f, -0.00623823144f, 0.0101458412f, -0.000363122177f, + -0.00968768448f, 0.00756290136f, -0.00470108353f, -0.0234390181f, 0.0108695952f, + 0.00246674079f, 0.01412981f, 0.0160553958f, 0.00782185886f, -0.0164537914f, + -0.00122756045f, 0.011533591f, -0.000478076283f, -0.00500984117f, 0.0151789226f, + 0.0332794227f, -0.00299129682f, -0.00671298802f, 0.00506960088f, 0.00189570524f, + 0.00116946094f, 0.00750314165f, -0.008844411f, 0.0145282075f, 0.0110687939f, + -0.0298000891f, -0.00403376855f, 0.00352913258f, -0.0228547025f, 0.0238374155f, + 0.00964784529f, 0.000522895949f, -0.0134392558f, -0.000701759534f, -0.00993336271f, + 0.0300125666f, -0.0103317602f, -0.0330935046f, -0.0187246539f, -0.0127088614f, + -0.0215798318f, -0.0271441098f, 0.00200858433f, -0.0182996988f, 0.000506296055f, + -0.00409352826f, -0.00478408299f, -0.00601579342f, -0.0145016471f, -0.00575351529f, + -0.00480400259f, 0.0190832112f, -0.0115070306f, -0.0301453657f, -0.0387507379f, + -0.0127487015f, 0.0165467523f, 0.025497403f, 0.0335184596f, -0.00930256769f, + 0.0146344462f, -0.0023538617f, -0.0224563051f, 0.00597927347f, -0.0106172776f, + 0.00270245899f, -0.0309155993f, 0.0246740486f, 0.0319779925f, 0.00732386298f, + -0.000553605729f, -0.0133396564f, 0.038697619f, 0.0174763445f, -0.00271241902f, + -0.0458687656f, -0.0055609569f, 0.00488368189f, 0.0117925489f, -0.0187379345f, + -0.0198667254f, -0.00541487802f, -0.00908344984f, -0.0320576727f, 0.030410964f, + 0.0150461234f, 0.000627890113f, -0.00158694771f, 0.0211415961f, 0.000294232712f, + -0.0206900798f, 0.00265099946f, -0.00690554641f, 0.00657354901f, 0.0009544926f, + 0.0270777103f, 0.0105774375f, 0.0056406362f, 0.00709146494f, -0.0142493295f, + -0.00717778411f, -0.0216462314f, -0.0111484732f, 0.0425753482f, -0.0159358755f, + -0.0127553409f, 9.98586038E-05f, -0.0307562407f, -0.0158030782f, 0.00296639698f, + -0.00406696834f, -0.0243818909f, 0.00208992371f, -0.00659346906f, -0.0182731375f, + -0.00201688427f, -0.0194152091f, -0.0177419428f, 0.00548791746f, 0.00621499168f, + 0.0283393003f, -0.00909008924f, 0.0231070202f, 0.000223268275f, -0.000871493248f, + 0.0181403384f, 0.0141032506f, -0.00748322206f, 0.000213100851f, 0.0204112008f, + 0.0177419428f, 0.00274229865f, 0.00526215928f, -0.0302781649f, 0.0163209941f, + -0.0188176148f, -0.0228015836f, 0.0181403384f, -0.00629467098f, 0.000120556564f, + -0.0294016916f, -0.0136915734f, 0.00916312914f, -0.00829993561f, -0.0370774716f, + 0.0218587108f, 0.00344613334f, -0.0200924836f, -0.0363337994f, 0.00610211259f, + -0.0190832112f, 0.00645403005f, -0.0106969569f, -0.027276909f, 0.0216727927f, + -0.0270777103f, -0.0190300923f, -0.00141430902f, -0.018618416f, 0.0246076491f, + -0.00518579967f, 0.00647726981f, 0.00930920802f, -0.0124034239f, -0.00869833212f, + 0.0106703974f, -0.00118689076f, 0.0271706693f, 0.00725082355f, 0.0255106818f, + -0.00866513234f, 0.0205174405f, 0.0235319771f, 0.00750978151f, -0.0119983871f, + -0.0309687201f, -0.0103383996f, 0.00650382973f, 0.00461476436f, 0.000466871366f, + -0.00938888732f, -0.0229078215f, -0.023346059f, -0.0360682011f, -0.0209556781f, + -0.00801441818f, 0.0521368757f, 0.0182598587f, -0.00467784377f, 0.00508952048f, + 0.000546135765f, 0.0217790306f, 0.020636959f, -0.0149664441f, -0.0176489837f, + 0.0144618079f, -0.0530930273f, -0.00141098909f, -0.0108231157f, 0.016281154f, + 0.000441556564f, 0.00258625997f, 0.0225094259f, 0.0208759978f, 0.0185652953f, + -0.0162545945f, -0.0219516698f, -0.00223766267f, 0.00416988786f, -0.00135454955f, + 0.00667978823f, -0.00653702905f, 0.0253646038f, -0.00525219925f, -0.00199862453f, + -0.0235585365f, -0.0269316304f, 0.0149930036f, -0.005813275f, -0.00689226668f, + 0.0179544203f, -0.0194948893f, 0.0178481806f, -0.0278346632f, -0.00512272026f, + 0.0145016471f, -0.0140766911f, -0.0253911633f, 0.0237577353f, 0.0209556781f, + -0.0154179605f, -0.0175560247f, -0.0184324961f, -0.012589342f, -0.020862719f, + 0.0118788676f, 0.030782802f, -0.0199995246f, 0.0178481806f, 0.0183793772f, + 0.00338803371f, 0.00960136577f, 0.00206834404f, -0.00733714318f, 0.0141032506f, + -0.0190832112f, -0.00469444366f, -0.0379008241f, -0.0249130875f, 0.0279409029f, + 0.00164504722f, 0.000566470611f, -0.0194284897f, 0.0219649505f, -0.036546275f, + 0.00663662842f, 0.00232066191f, 0.0217923112f, 0.0321373492f, 0.0170912277f, + 0.00304275635f, 0.0292954519f, 0.0113410316f, 0.00425952673f, -0.00956152566f, + 0.00352913258f, 0.00014369264f, 0.0049401219f, 0.0266129132f, -0.00549455732f, + -0.0155905988f, -0.0124764629f, -0.007463302f, -0.0100661619f, 0.00591951422f, + 0.0191097725f, -0.0176091436f, 0.00271407887f, -0.00559415668f, 0.00168571691f, + -0.0137978131f, -0.0107434364f, -0.00167492696f, -0.0184059367f, 0.00560743641f, + 0.00877801236f, 0.0145282075f, -0.0232929401f, 0.00578339491f, 0.000506296055f, + -0.0210486371f, -0.0135454945f, -0.0281268209f, -0.025125565f, -0.0163077135f, + -0.0113808718f, -0.000884773151f, 0.0195214488f, -0.0170381069f, 0.00756290136f, + 0.0115269506f, -0.0260949973f, -0.00650382973f, 0.00426616706f, -0.012237425f, + 0.00562735647f, -0.0121311862f, -0.00591619406f, 0.0174232256f, -0.0259887576f, + 0.0109691946f, -0.0248732474f, 0.0100661619f, -0.00613199221f, -0.00467784377f, + -0.037289951f, 0.0230804607f, 0.029242333f, -0.00617847219f, 0.0142360497f, + 0.00167492696f, -0.013147098f, -0.00838625524f, -0.015205482f, -0.0237444565f, + -0.024753727f, 0.0125295827f, -0.00425620703f, -0.0139970118f, -0.0231468603f, + 0.0307296813f, -0.0154046807f, -0.0440626964f, 0.018618416f, 0.225439534f, + -0.00108231162f, -0.000843273476f, 0.0148203652f, -0.00670966785f, 0.0110422345f, + 0.0157101173f, -0.0147539657f, -0.0214470327f, -0.0116199097f, -0.0119386278f, + -0.0112082334f, 0.0169717092f, -2.24746691E-05f, 0.0100263217f, -0.0215532724f, + -0.0060655931f, -0.0171576273f, -0.0105973575f, -0.0217259116f, 0.0226023849f, + 0.0340762138f, 0.00237378152f, -0.0128283808f, 0.0148734841f, 0.0034793329f, + -0.0201854426f, 0.02573644f, 0.0229875017f, 0.00882449187f, -0.03489957f, + 0.0145813273f, -0.00176788634f, -0.0198268853f, -0.0106305573f, 0.00226422236f, + -0.000865683309f, 0.00358889205f, -0.0135986144f, -0.0105641577f, 0.00200858433f, + -0.008678413f, 0.0194683298f, 0.0146078868f, 0.0228414219f, 0.0398928113f, + -0.00718442444f, -0.0145149278f, 0.003217055f, 0.00781521946f, -0.0259621982f, + 0.000269747921f, 0.0109094353f, 0.0343418121f, 0.0120780664f, -0.00198700465f, + 0.0276221856f, -5.04221098E-05f, 0.00151307823f, -0.00714458479f, 0.00348597299f, + -0.00330171431f, 0.00109144149f, 0.0197870471f, -0.0150992433f, 0.0535976626f, + -0.024660768f, -0.00193720497f, -0.000455251458f, -0.0120847067f, -0.0067627877f, + -0.00237710145f, -0.00700514577f, 0.00241528125f, 0.0182864182f, -0.012071426f, + 0.00563731603f, 0.0203580819f, 0.00869169272f, 0.0125627825f, -0.00731058326f, + -0.00641087024f, 0.00111717137f, 0.0159491561f, 0.00795465801f, -0.0157765169f, + 0.0209025573f, 0.029614171f, -0.0261613969f, -0.00472100358f, 0.0126623819f, + -0.0205971207f, -0.0115933502f, -0.00456496468f, 0.0113808718f, 0.0070184255f, + 0.031393677f, 0.0195612889f, -0.00259787985f, -0.00527875917f, -0.0156968385f, + 0.0287376978f, -0.00298465695f, -0.0325091891f, -0.0180872194f, -0.0121776657f, + 0.0110023944f, 0.00835969485f, -0.0145282075f, -0.00673290761f, -0.00673954794f, + -0.0362275578f, 0.00117859081f, -0.0142758889f, -0.000151785076f, -0.00227252231f, + 0.00761602074f, 0.010643837f, -0.00766250072f, -0.0164803527f, 0.00324195484f, + -0.0177021027f, 0.00210486376f, 0.0224164668f, -0.00453176489f, -0.0338106193f, + -0.0260949973f, -0.0027240389f, 0.00402712869f, -0.0225625448f, 0.0192425698f, + -0.0300656874f, 0.0350323692f, 0.00645403005f, -0.0137978131f, 0.0107301567f, + 0.013591975f, 0.00509616034f, -0.0114472713f, 0.022642225f, 0.00324195484f, + 0.00457824441f, 0.0136118941f, 0.000350464776f, 0.0130275786f, 0.010902795f, + 0.0164936315f, 0.018153619f, -0.024421731f, -0.0309421606f, -0.0226555038f, + -0.0237046164f, 0.00681258691f, -0.00761602074f, 0.0134126963f, 0.0022675423f, + -0.0178083424f, -0.0187379345f, 0.0118921474f, 0.0076359408f, -0.0260949973f, + -0.00419312762f, 0.00595603371f, -0.000536175852f, -0.0189371333f, -0.00093291275f, + -0.169876441f, 0.00245180097f, 0.019136332f, -0.00802769791f, 0.0314999148f, + 0.00315065566f, 0.0112414332f, -0.0152851613f, 0.00383457029f, -0.00254144031f, + 0.0397865698f, -0.0223766267f, -0.0369977914f, -0.0131670181f, 0.0123104649f, + 0.000660674879f, -0.0206502397f, 0.0181137789f, 0.0116929496f, 0.0175161846f, + 0.0316592753f, -0.0146610066f, -0.0206502397f, 0.0160952359f, -0.0102321608f, + 0.00862529315f, 0.000525385898f, 0.0108231157f, -0.00460812403f, -0.0149930036f, + -0.0232796595f, -0.00348265306f, 0.0135255754f, 0.0291360933f, 0.00661670882f, + -0.00360549195f, -0.0122241452f, 0.00205838401f, -0.0103317602f, -0.0103782397f, + 0.0207963195f, -0.00966776535f, 0.0154179605f, -0.00599919353f, -0.00995328277f, + 0.0188707337f, 0.0345542915f, -0.0023854014f, 0.0158694778f, -0.0190566517f, + -0.0044985651f, -0.0328544639f, -0.0196542479f, -0.00234224182f, 0.0295876097f, + 0.0176489837f, 0.032323271f, -0.0163475536f, 0.00369513128f, -0.0118589476f, + 0.00875145197f, -0.00938224699f, 0.0110488739f, 0.00609879289f, -0.0149531644f, + -0.0163873937f, -0.0169982687f, 0.0157101173f, -0.0257497206f, 0.0157366786f, + -0.0343418121f, 0.00630795117f, 0.00132549973f, -0.00224928255f, 0.0170513876f, + 0.00206170394f, -0.0064175101f, -0.00396736944f, -0.0162413139f, -0.00283857808f, + 0.00229908223f, 0.0376352295f, -0.0113343922f, -0.00647394964f, 0.00522895949f, + 0.00646730978f, -0.00785505865f, -0.00471436325f, -0.00404372858f, -0.0226953439f, + 0.0032386349f, -0.0237842947f, 0.0051194001f, -0.0287908167f, 0.00190068525f, + 0.016374113f, 0.00686570676f, -0.00547795743f, -0.00899048988f, -0.0149531644f, + 0.0012117906f, 0.0159889963f, -0.00563067617f, 0.020862719f, 0.00715122465f, + 0.0053883181f, -0.0103981597f, 0.0116929496f, 0.0312343184f, -0.0110687939f, + -0.0220579095f, 0.00934240781f, 0.0112945521f, -0.00479072286f, 0.0110555142f, + 0.00756290136f, 0.01932225f, -0.0133595765f, 0.000450686493f, 0.00122673053f, + 0.0844601467f, 0.0145547669f, 0.0211283155f, 0.0243951716f, -0.0251388457f, + -0.029242333f, -0.111019939f, -0.00749650178f, -0.0111152735f, 0.0209689569f, + -0.0076359408f, 0.0298000891f, -0.00591951422f, 0.0145282075f, 0.00177120627f, + 0.00275889854f, 0.000104319814f, -0.0345808528f, -0.0155241992f, -0.0145813273f, + 0.0245014094f, 0.0104180789f, -0.00419312762f, -0.0212478358f, -0.00725746388f, + 0.0281799417f, -0.0216329526f, 0.0160288364f, 0.00370841124f, -0.0362010002f, + 0.0224164668f, 0.0127553409f, -0.0161085147f, 0.0177552216f, 0.0135255754f, + 0.0143954083f, 0.00340629346f, -0.00498660142f, 0.0243818909f, -0.00597927347f, + 0.00326851453f, -0.0137845334f, -0.0339434184f, -0.00417984743f, 0.0116464701f, + -0.0340496562f, 0.00460480433f, 0.0052920389f, 0.0100329621f, -0.0220579095f, + -0.00893737096f, 0.0070981048f, 0.00857881363f, 0.00189736532f, 0.0293751322f, + -0.0170912277f, -0.0216063932f, 0.00242690113f, -0.024660768f, -0.0096146455f, + 0.0108563155f, 0.0148867648f, 0.00144335884f, -0.00531859882f, -0.0362806767f, + 0.00548459729f, 0.00395076955f, 0.00950176641f, -0.0220579095f, 0.00802105758f, + -0.0145016471f, 0.0181403384f, -0.0063212309f, -0.000105720428f, 0.0226953439f, + -0.0160288364f, 0.016520191f, 0.0147141255f, -0.0192558505f, 0.0205041617f, + -0.0256302003f, 0.00835305545f, -0.0253114831f, -0.00532855885f, 0.0286048986f, + -0.0127619812f, 0.00752970157f, -0.0176091436f, 0.0115468707f, -0.00156868785f, + 0.0253911633f, 0.0197472069f, 0.00592283392f, -0.000907182985f, -0.0183129776f, + 0.0077952994f, -0.0110223144f, 0.0192956906f, 0.00390760973f, -0.0176755432f, + -0.0199729651f, 0.0389366597f, -0.0137048541f, 0.00368185132f, -0.0341824554f, + -0.00388768991f, -0.0296938494f, 0.0189636927f, -0.0524555929f, 0.0309421606f, + -0.00386112998f, 0.00865185261f, -0.0241826922f, 0.0186316948f, 0.0270245895f, + -0.00507624075f, -0.0129877394f, 0.0184324961f, 0.00382129033f, 0.0384851396f, + -0.0295079313f, 0.00613531237f, -0.0210353564f, 0.012516303f, 0.0177950617f, + -0.0138774924f, 0.0189371333f, -0.00636771042f, -0.000126574014f, -0.029056415f, + 0.00665986817f, -0.00294647715f, 0.000263522961f, -0.0198534466f, -0.00535511831f, + 0.0369446725f, -0.030225046f, -0.00420308718f, -0.0130142989f, -0.0264933947f, + -0.0226953439f, -0.0106106373f, -0.00508620031f, -0.013240057f, -0.0110621545f, + 0.0223899055f, 0.00990016293f, 0.0491090603f, -0.0238374155f, -0.0254310034f, + 0.00958808605f, -0.0114339916f, 0.0202784035f, 0.0168389101f, 0.0110488739f, + 0.00617847219f, 0.0166264307f, 0.00269581913f, 0.00739026256f, 0.0261348374f, + -0.0189105738f, -0.010902795f, -0.0131138982f, -0.0266527534f, 0.031818632f, + 0.0126225417f, 0.00265099946f, 0.0208892785f, -0.00455832481f, 0.0212611146f, + 0.0184590574f, 0.00597927347f, 0.00397400931f, -0.016281154f, 0.00729730353f, + 0.0107899159f, 0.0179278608f, -0.0358291604f, 0.00235054176f, -0.00723754382f, + -0.00348929293f, -0.00451848516f, -0.0250458848f, 0.00532523869f, 0.00425620703f, + 0.0079878578f, 0.000590125448f, 0.01548436f, -0.00934904721f, 0.00942872651f, + -0.0384851396f, 0.0121112661f, 0.0099665625f, 0.00859209336f, -0.0127221411f, + 0.00713130459f, -0.0103118401f, 0.000337184872f, 0.0013080698f, -0.000826673582f, + 0.00736370264f, -0.0185652953f, 0.000161848744f, 0.0133861359f, -0.00597595377f, + 0.00424956717f, 0.034952689f, 0.0338902958f, -0.000162263736f, 0.0100728022f, + -0.00863857288f, -0.0110621545f, 0.000502976123f, 0.00761602074f, -0.00870497245f, + 0.0134126963f, 0.00196542474f, 0.00656690914f, -0.00439564604f, 0.015391401f, + 0.0214337539f, 0.0284720995f, -0.00176456629f, 0.00932248775f, 0.0169717092f, + -0.0207564794f, -0.0272503477f, 0.00905688945f, 0.00983376335f, 0.000620420207f, + 0.0134790959f, -0.00633451063f, 0.00481728278f, 0.0129213398f, 0.014647726f, + 0.00096694252f, -0.00460148416f, 0.0157765169f, 0.00543811778f, 0.0158296376f, + -0.0359885208f, 0.00147821847f, -0.0258028395f, -0.0110090347f, -0.0223633461f, + 0.0167990699f, -0.0115003912f, 0.00705162529f, 0.00604899321f, -0.00887097139f, + 0.0017745262f, -0.0214603133f, 0.0415395163f, 0.00866513234f, -0.00297801686f, + -0.0149398837f, -0.0185652953f, 0.014647726f, 0.0138907721f, -0.00124499039f, + 0.0171310678f, -0.00336479396f, 0.0158030782f, -0.0135654146f, 0.00277715852f, + 0.0011130214f, 0.00737034297f, 0.0229211021f, 0.00273731886f, -0.000847423449f, + 0.00276553864f, -0.0142094893f, -0.0248334073f, -0.00493016187f, 0.0069387462f, + -0.0224563051f, -0.0243420508f, 0.0176224224f, 0.0113808718f, -0.0127487015f, + -0.0202784035f, -0.00921624806f, 0.00799449813f, 0.0174232256f, -0.0115402304f, + 0.0167061109f, -0.000982712372f, -0.0122175049f, 0.0237710159f, -0.0221110284f, + -0.021619672f, -0.00411344785f, -0.0155640393f, 0.000650299946f, 0.00979392417f, + -0.0121311862f + ] + } + }, + ]; + + nestedVectorCollection.InsertMany(movies); + + var indexModel = new CreateVectorSearchIndexModel( + e => e.Plot.PlotEmbedding, + nestedVectorIndexName, + VectorSimilarity.Euclidean, + dimensions: 1536, + e => e.Available, e => e.Title, e => e.Year, e => e.Plot.Rating, e => e.Plot.Plot); + + indexModel = indexModel.WithIncludedStoredFields(e => e.Title, e => e.Year); + + nestedVectorCollection.SearchIndexes.CreateOne(indexModel); + + while (TryGetIndex(nestedVectorCollection, nestedVectorIndexName, out var indexDocument) + && indexDocument["status"].AsString != "READY") + { + Thread.Sleep(10000); // Server internal polling of indexes is 10 seconds + } + + float[] vector = + [ + -0.0329607055f, -0.0246873293f, -0.018857453f, -0.00159607758f, -0.00163923728f, + 0.00919632893f, -0.0200526435f, -0.0178747419f, 0.0219118297f, -0.0105110388f, + 0.0259489194f, 0.0255372413f, -0.00599255366f, -0.0202252828f, 0.0161616355f, + -0.00659346906f, 0.0321639106f, -0.00854561385f, 0.00182266592f, -0.0170381069f, + 0.00623491174f, 0.0336778201f, 0.00853897352f, -0.015391401f, 0.00287509779f, + 0.0174232256f, -0.00105741178f, -0.0365993977f, 0.0219118297f, -0.00752970157f, + -0.00838625524f, -0.0141430907f, 0.0111418338f, -0.00401384896f, -0.0456828438f, + -0.00699850591f, -0.00693210633f, -0.035138607f, -0.0120249465f, -0.0143954083f, + 0.0249396469f, 0.0187246539f, 0.0130474987f, -0.00254808017f, -0.0327482261f, + -0.0298266485f, 0.0151789226f, -0.00161350751f, -0.0247935671f, 0.00802105758f, + 0.0171177872f, 0.025497403f, -0.0158030782f, -0.000277010346f, 0.00375821092f, + -0.0138907721f, -0.00198534457f, 0.00968104508f, -0.00380801037f, -0.00334653398f, + -0.00431264658f, -0.00396404928f, -0.0186980944f, -0.00292987726f, 0.0282596201f, + -0.00361877191f, -0.0270245895f, -0.00453840476f, -0.0221375879f, -0.00841945503f, + 0.0374227501f, 0.031021839f, -0.00756954122f, -0.0137048541f, 0.0243951716f, + -0.0281002615f, -0.0208095983f, -0.0129213398f, 0.015391401f, -0.0116863092f, + 0.0317920744f, -0.0221110284f, -0.0115070306f, 0.00827337615f, 0.0276753046f, + -0.00588299427f, 0.00184424571f, 0.0134458961f, -0.0151258027f, -0.00591619406f, + -0.0127287814f, 0.00393416965f, 0.0120647866f, 0.0146610066f, -0.0221508685f, + 0.00187080551f, -0.0215798318f, 0.025497403f, -0.00239868136f, -0.0155507596f, + -0.000952002592f, -0.00182432588f, 0.00036415967f, -0.00706490502f, -0.0218188707f, + -0.00417320756f, -0.00522231963f, -0.0103383996f, 0.010643837f, 0.00950840581f, + -0.027276909f, 0.00972088426f, 0.00276719849f, -0.0619374402f, 0.00929592829f, + -0.0240764525f, 0.0176622625f, -0.00414332794f, 0.00458156457f, -0.0122971842f, + 0.0368384346f, 0.0150062833f, 0.0108363964f, -0.00598591333f, 0.0273034684f, + -0.0117527088f, 0.00549455732f, -0.0192824099f, -0.0207830388f, -0.00164587726f, + 0.03237639f, 0.0269714706f, 0.00533519872f, -0.000216005821f, 0.00595603371f, + 0.0275425054f, -0.0158030782f, 0.0184988957f, -0.00823353603f, -0.00971424486f, + 0.0128748603f, 0.0228547025f, -0.0237710159f, -0.0147805251f, -0.00475088321f, + -0.00412672805f, -0.00992008299f, 0.0200128052f, 0.0124167036f, 0.00289833755f, + 0.0117726289f, -0.0242756512f, 0.00572363567f, -0.0244748499f, 0.0277284253f, + -0.00963456556f, -0.00384453009f, 0.0142493295f, -0.00675282767f, -0.0227617435f, + 0.0133462967f, 0.0100661619f, 0.0139837312f, 0.00598259363f, 0.0315530337f, + 0.0216860715f, 0.0100528821f, 0.0227086246f, 0.00318717537f, -0.0230007824f, + 0.00793473888f, 0.0174232256f, -0.0314733572f, 0.00603903318f, -0.0176755432f, + 0.019933125f, 0.012609262f, 0.0109891146f, -0.0253911633f, 0.0156437177f, + -0.0300125666f, 0.00310085597f, 0.0158694778f, 0.0294813719f, -0.0366525166f, + -0.00306267617f, 0.00194218499f, -0.00492020184f, 0.00354241254f, -0.0116863092f, + 0.0273300279f, 0.0153250014f, 0.00150145835f, -0.0116398297f, -0.662507474f, + -0.00483056251f, -0.0130142989f, 0.00731722312f, 0.0309155993f, -0.0056240363f, + 0.000952832634f, -0.00241528125f, 0.00496668136f, 0.00299627683f, 0.00120930059f, + 0.0178614613f, -0.00139521912f, -0.0322967097f, -0.0186582562f, -0.0227219034f, + -0.0148734841f, 0.00153465813f, 0.0191628914f, 0.00692546647f, -0.0104180789f, + 0.0350058079f, 0.00233560195f, 0.00208494393f, 0.000625400164f, 0.00294979708f, + 0.0173169859f, 0.00512272026f, -0.0110023944f, -0.0118589476f, -0.00615191227f, + 0.00842609443f, -0.00593611412f, 0.0267855525f, 0.0558286868f, -0.0118257478f, + -0.0212611146f, 0.0191097725f, 0.0100661619f, 0.0320842303f, -0.0161483549f, + -0.00554767717f, 0.0216462314f, -0.0142891696f, 0.00837961491f, -0.0202784035f, + 0.02844554f, -0.0192558505f, -0.000318925013f, -0.00802769791f, 0.00715786451f, + 0.00816713646f, -0.00343617331f, 0.00770898024f, 0.00790817849f, 0.013054139f, + 0.031871751f, -0.00922952872f, -0.00446204515f, -0.0144352484f, -0.00630463101f, + 0.0101724006f, 0.00809409749f, -0.0133396564f, -0.0175161846f, -0.00178448611f, + -0.000200339695f, 0.0460812412f, 0.0176224224f, -0.0238905344f, 0.016281154f, + -0.00121096056f, -0.0229476616f, -0.00285019795f, -0.00865849294f, 0.00255970005f, + 0.0230804607f, -0.00506296055f, -0.000187474798f, -0.00351585262f, -0.0035490524f, + -0.0264004357f, -0.0373961888f, 0.0116531095f, 0.0378477052f, -0.00865185261f, + -0.0215001535f, -0.00796129834f, 0.0197604876f, 0.00161516748f, -0.00483388267f, + 0.00134126958f, -0.0114539107f, -0.00755626149f, 0.00737034297f, 0.0295079313f, + -0.00828001555f, -0.00434916606f, 0.0045948443f, -0.0258957986f, 0.00978728384f, + -0.00321871508f, -0.0118124681f, -0.00614195224f, -0.00457492471f, -0.00468116347f, + -0.0239303745f, 0.00272071897f, 0.0342886932f, -0.0107633565f, 0.00423628697f, + 0.00576347532f, -0.0124432631f, 0.00213806331f, 0.00920296833f, -0.0218587108f, + 0.0166397113f, -0.00167658704f, 0.0236116573f, -0.0271042697f, -0.00540823815f, + 0.00370841124f, 0.00661670882f, -0.0149000445f, 0.025590362f, 0.030782802f, + 0.0166662708f, 0.00230074208f, 0.00998648256f, -0.00276719849f, -5.31714613E-05f, + -0.000995992217f, 0.0191230513f, 0.00942208711f, 0.0190300923f, 0.01412981f, + 0.0197604876f, -0.010550878f, 0.019229291f, 0.00835305545f, -0.00587635441f, + 0.0130474987f, 0.0118257478f, 0.00525883911f, 0.00352249271f, -0.0234257374f, + -0.0245412495f, -0.00723090395f, -0.0595470592f, 0.0287908167f, 0.018525457f, + 0.000966112479f, -0.0189636927f, -0.0249396469f, -0.00766250072f, 0.00865849294f, + -0.0291360933f, -0.010530958f, 0.00376153085f, -0.01932225f, 0.0152586019f, + 0.0225625448f, -0.00917640887f, 0.00880457181f, 0.00513599999f, -0.0102587203f, + 0.0228945427f, 0.00439232588f, 0.00181270589f, -0.0205174405f, 0.00790153909f, + -0.0221375879f, 0.000317472528f, 0.0104711987f, -0.0114207109f, -0.00400056876f, + -0.0337840579f, -0.00106820173f, -0.00555099687f, 0.0217923112f, 0.0115468707f, + -0.00472764345f, -0.0134724556f, 0.0118788676f, 0.00477744313f, 0.0380070657f, + 0.00471768342f, 0.0114207109f, 0.00899048988f, 0.0223367866f, 0.00869169272f, + 0.00616851216f, -0.000866513292f, -0.0132334176f, 0.00677606743f, -0.0050198012f, + 0.00570371561f, 0.00187744538f, 0.0209955163f, 0.0373961888f, 0.0291626547f, + -0.000258543005f, 0.0214204732f, 0.00384121016f, -0.000275557861f, -0.0432924628f, + 0.00559415668f, -0.0300125666f, 0.0502245687f, 0.00601579342f, 0.0160553958f, + -0.015112523f, -0.0123901442f, -0.0194683298f, -0.011699589f, 0.0322967097f, + 0.0102985604f, 0.00270577893f, 0.0144618079f, -0.00515259989f, -0.0124764629f, + -0.0241826922f, 0.0193488095f, -0.00826009549f, -0.0479935482f, -0.013127178f, + 0.0124631831f, 0.00678270729f, 0.0124100633f, 0.000304400135f, 0.00514596002f, + 0.0234655775f, -0.0200924836f, 0.0314202346f, 0.016892029f, -0.00617515203f, + -0.00471436325f, -0.00117527088f, 0.012257345f, -0.000128234009f, -0.0231070202f, + 0.0274362676f, -0.00514264032f, -0.024753727f, -0.00298133679f, -0.0183660984f, + 0.0289236158f, 0.00776873995f, -0.0185785759f, 0.0183793772f, -0.00215964322f, + -0.000189238533f, 0.00240864139f, -0.00541487802f, -0.000102089209f, -0.0246873293f, + 0.0242756512f, -0.00517251994f, 0.0274097081f, 0.0250857249f, -0.000887263101f, + -0.0196808074f, 0.0138376523f, 0.00308093615f, 0.0158960372f, 0.00401384896f, + 0.01806066f, 0.0133994156f, -0.0120913461f, -0.0120315868f, -0.00126574014f, + 0.0119983871f, 0.0156038785f, -0.0167990699f, 0.00709146494f, -0.0123038245f, + -0.00249662064f, 0.00691882614f, 0.0019571248f, 0.00228746235f, -0.00237876154f, + -0.0292157736f, 0.0271042697f, 0.0102321608f, -0.00639095064f, -0.0024717208f, + -0.0137845334f, 0.00308425608f, -0.0243553314f, 0.0244615711f, 0.0116066299f, + 0.0190699324f, -0.0153250014f, -0.0106969569f, -0.0206103995f, -0.0150461234f, + 0.0254442822f, -0.0250724461f, 0.00485380227f, -0.0178349018f, 0.0100064026f, + 0.00608219299f, -0.00266261934f, -0.0204643216f, 0.0127686206f, 0.0180872194f, + 0.00740354275f, -0.0194152091f, -0.0208494384f, -0.0150859626f, 0.00840617437f, + 0.0141032506f, 0.00736370264f, -0.0104114395f, 0.00162927737f, 0.00807417743f, + -0.0194550492f, -0.0189769734f, 0.01932225f, 0.00924280845f, 0.00859873369f, + -0.0152718816f, -0.00693210633f, 0.000851573364f, 0.116863094f, 0.0383789018f, + -0.0210884772f, -0.00605895277f, -0.0188441742f, 0.0142626092f, -0.021008797f, + -0.00882449187f, -0.00583651476f, -0.0275425054f, -0.012423344f, 0.000378892059f, + 0.00940216705f, 0.0113144722f, 0.0259489194f, 0.01412981f, 0.0065901489f, + -0.00812729727f, -0.0162944328f, -0.00734378304f, 0.0146875661f, 0.00339965359f, + 0.0212743953f, 0.0150859626f, -0.0121577457f, -0.0229078215f, 0.000607555266f, + 0.0166131519f, -0.00984704401f, -0.0217923112f, -0.0328544639f, 0.00464796415f, + -0.00858545303f, 0.021101756f, 0.00589959417f, 0.0114539107f, 0.0286048986f, + -0.023346059f, 0.0109824752f, -0.0135056553f, 0.0252450835f, -0.00724418368f, + -0.00729066366f, -0.00990680326f, 0.00248998078f, -0.0147274053f, -0.0254310034f, + 0.00171476672f, -0.00985368341f, -0.0296938494f, 0.0166662708f, -0.0256965999f, + -0.0460015647f, -0.0148203652f, -0.00847921427f, 0.00632787077f, 0.00563067617f, + 0.0380867459f, -0.010179041f, 0.0385382622f, -0.022270387f, -0.0185652953f, + -0.0109891146f, -0.0188707337f, 0.0162545945f, -0.014647726f, -0.0124565437f, + -0.00287509779f, -0.0202518422f, -0.00561407628f, -0.013240057f, -0.0237046164f, + -0.0104114395f, 0.00758282095f, -0.006165192f, 0.0200128052f, 0.0156304389f, + -0.0301453657f, 0.0179544203f, 0.0206103995f, -0.019840166f, -0.0220313482f, + -0.00776873995f, -0.0241694134f, 0.00755626149f, 0.00452844473f, 0.0105043985f, + -0.0174365044f, -0.0248068478f, 0.0241295733f, 0.0111750336f, 0.0039142496f, + 0.0147938048f, 0.00678934716f, -0.017263867f, 0.0028103583f, -0.00505632069f, + 0.0263074767f, 0.000700099568f, -0.00623823144f, 0.0101458412f, -0.000363122177f, + -0.00968768448f, 0.00756290136f, -0.00470108353f, -0.0234390181f, 0.0108695952f, + 0.00246674079f, 0.01412981f, 0.0160553958f, 0.00782185886f, -0.0164537914f, + -0.00122756045f, 0.011533591f, -0.000478076283f, -0.00500984117f, 0.0151789226f, + 0.0332794227f, -0.00299129682f, -0.00671298802f, 0.00506960088f, 0.00189570524f, + 0.00116946094f, 0.00750314165f, -0.008844411f, 0.0145282075f, 0.0110687939f, + -0.0298000891f, -0.00403376855f, 0.00352913258f, -0.0228547025f, 0.0238374155f, + 0.00964784529f, 0.000522895949f, -0.0134392558f, -0.000701759534f, -0.00993336271f, + 0.0300125666f, -0.0103317602f, -0.0330935046f, -0.0187246539f, -0.0127088614f, + -0.0215798318f, -0.0271441098f, 0.00200858433f, -0.0182996988f, 0.000506296055f, + -0.00409352826f, -0.00478408299f, -0.00601579342f, -0.0145016471f, -0.00575351529f, + -0.00480400259f, 0.0190832112f, -0.0115070306f, -0.0301453657f, -0.0387507379f, + -0.0127487015f, 0.0165467523f, 0.025497403f, 0.0335184596f, -0.00930256769f, + 0.0146344462f, -0.0023538617f, -0.0224563051f, 0.00597927347f, -0.0106172776f, + 0.00270245899f, -0.0309155993f, 0.0246740486f, 0.0319779925f, 0.00732386298f, + -0.000553605729f, -0.0133396564f, 0.038697619f, 0.0174763445f, -0.00271241902f, + -0.0458687656f, -0.0055609569f, 0.00488368189f, 0.0117925489f, -0.0187379345f, + -0.0198667254f, -0.00541487802f, -0.00908344984f, -0.0320576727f, 0.030410964f, + 0.0150461234f, 0.000627890113f, -0.00158694771f, 0.0211415961f, 0.000294232712f, + -0.0206900798f, 0.00265099946f, -0.00690554641f, 0.00657354901f, 0.0009544926f, + 0.0270777103f, 0.0105774375f, 0.0056406362f, 0.00709146494f, -0.0142493295f, + -0.00717778411f, -0.0216462314f, -0.0111484732f, 0.0425753482f, -0.0159358755f, + -0.0127553409f, 9.98586038E-05f, -0.0307562407f, -0.0158030782f, 0.00296639698f, + -0.00406696834f, -0.0243818909f, 0.00208992371f, -0.00659346906f, -0.0182731375f, + -0.00201688427f, -0.0194152091f, -0.0177419428f, 0.00548791746f, 0.00621499168f, + 0.0283393003f, -0.00909008924f, 0.0231070202f, 0.000223268275f, -0.000871493248f, + 0.0181403384f, 0.0141032506f, -0.00748322206f, 0.000213100851f, 0.0204112008f, + 0.0177419428f, 0.00274229865f, 0.00526215928f, -0.0302781649f, 0.0163209941f, + -0.0188176148f, -0.0228015836f, 0.0181403384f, -0.00629467098f, 0.000120556564f, + -0.0294016916f, -0.0136915734f, 0.00916312914f, -0.00829993561f, -0.0370774716f, + 0.0218587108f, 0.00344613334f, -0.0200924836f, -0.0363337994f, 0.00610211259f, + -0.0190832112f, 0.00645403005f, -0.0106969569f, -0.027276909f, 0.0216727927f, + -0.0270777103f, -0.0190300923f, -0.00141430902f, -0.018618416f, 0.0246076491f, + -0.00518579967f, 0.00647726981f, 0.00930920802f, -0.0124034239f, -0.00869833212f, + 0.0106703974f, -0.00118689076f, 0.0271706693f, 0.00725082355f, 0.0255106818f, + -0.00866513234f, 0.0205174405f, 0.0235319771f, 0.00750978151f, -0.0119983871f, + -0.0309687201f, -0.0103383996f, 0.00650382973f, 0.00461476436f, 0.000466871366f, + -0.00938888732f, -0.0229078215f, -0.023346059f, -0.0360682011f, -0.0209556781f, + -0.00801441818f, 0.0521368757f, 0.0182598587f, -0.00467784377f, 0.00508952048f, + 0.000546135765f, 0.0217790306f, 0.020636959f, -0.0149664441f, -0.0176489837f, + 0.0144618079f, -0.0530930273f, -0.00141098909f, -0.0108231157f, 0.016281154f, + 0.000441556564f, 0.00258625997f, 0.0225094259f, 0.0208759978f, 0.0185652953f, + -0.0162545945f, -0.0219516698f, -0.00223766267f, 0.00416988786f, -0.00135454955f, + 0.00667978823f, -0.00653702905f, 0.0253646038f, -0.00525219925f, -0.00199862453f, + -0.0235585365f, -0.0269316304f, 0.0149930036f, -0.005813275f, -0.00689226668f, + 0.0179544203f, -0.0194948893f, 0.0178481806f, -0.0278346632f, -0.00512272026f, + 0.0145016471f, -0.0140766911f, -0.0253911633f, 0.0237577353f, 0.0209556781f, + -0.0154179605f, -0.0175560247f, -0.0184324961f, -0.012589342f, -0.020862719f, + 0.0118788676f, 0.030782802f, -0.0199995246f, 0.0178481806f, 0.0183793772f, + 0.00338803371f, 0.00960136577f, 0.00206834404f, -0.00733714318f, 0.0141032506f, + -0.0190832112f, -0.00469444366f, -0.0379008241f, -0.0249130875f, 0.0279409029f, + 0.00164504722f, 0.000566470611f, -0.0194284897f, 0.0219649505f, -0.036546275f, + 0.00663662842f, 0.00232066191f, 0.0217923112f, 0.0321373492f, 0.0170912277f, + 0.00304275635f, 0.0292954519f, 0.0113410316f, 0.00425952673f, -0.00956152566f, + 0.00352913258f, 0.00014369264f, 0.0049401219f, 0.0266129132f, -0.00549455732f, + -0.0155905988f, -0.0124764629f, -0.007463302f, -0.0100661619f, 0.00591951422f, + 0.0191097725f, -0.0176091436f, 0.00271407887f, -0.00559415668f, 0.00168571691f, + -0.0137978131f, -0.0107434364f, -0.00167492696f, -0.0184059367f, 0.00560743641f, + 0.00877801236f, 0.0145282075f, -0.0232929401f, 0.00578339491f, 0.000506296055f, + -0.0210486371f, -0.0135454945f, -0.0281268209f, -0.025125565f, -0.0163077135f, + -0.0113808718f, -0.000884773151f, 0.0195214488f, -0.0170381069f, 0.00756290136f, + 0.0115269506f, -0.0260949973f, -0.00650382973f, 0.00426616706f, -0.012237425f, + 0.00562735647f, -0.0121311862f, -0.00591619406f, 0.0174232256f, -0.0259887576f, + 0.0109691946f, -0.0248732474f, 0.0100661619f, -0.00613199221f, -0.00467784377f, + -0.037289951f, 0.0230804607f, 0.029242333f, -0.00617847219f, 0.0142360497f, + 0.00167492696f, -0.013147098f, -0.00838625524f, -0.015205482f, -0.0237444565f, + -0.024753727f, 0.0125295827f, -0.00425620703f, -0.0139970118f, -0.0231468603f, + 0.0307296813f, -0.0154046807f, -0.0440626964f, 0.018618416f, 0.225439534f, + -0.00108231162f, -0.000843273476f, 0.0148203652f, -0.00670966785f, 0.0110422345f, + 0.0157101173f, -0.0147539657f, -0.0214470327f, -0.0116199097f, -0.0119386278f, + -0.0112082334f, 0.0169717092f, -2.24746691E-05f, 0.0100263217f, -0.0215532724f, + -0.0060655931f, -0.0171576273f, -0.0105973575f, -0.0217259116f, 0.0226023849f, + 0.0340762138f, 0.00237378152f, -0.0128283808f, 0.0148734841f, 0.0034793329f, + -0.0201854426f, 0.02573644f, 0.0229875017f, 0.00882449187f, -0.03489957f, + 0.0145813273f, -0.00176788634f, -0.0198268853f, -0.0106305573f, 0.00226422236f, + -0.000865683309f, 0.00358889205f, -0.0135986144f, -0.0105641577f, 0.00200858433f, + -0.008678413f, 0.0194683298f, 0.0146078868f, 0.0228414219f, 0.0398928113f, + -0.00718442444f, -0.0145149278f, 0.003217055f, 0.00781521946f, -0.0259621982f, + 0.000269747921f, 0.0109094353f, 0.0343418121f, 0.0120780664f, -0.00198700465f, + 0.0276221856f, -5.04221098E-05f, 0.00151307823f, -0.00714458479f, 0.00348597299f, + -0.00330171431f, 0.00109144149f, 0.0197870471f, -0.0150992433f, 0.0535976626f, + -0.024660768f, -0.00193720497f, -0.000455251458f, -0.0120847067f, -0.0067627877f, + -0.00237710145f, -0.00700514577f, 0.00241528125f, 0.0182864182f, -0.012071426f, + 0.00563731603f, 0.0203580819f, 0.00869169272f, 0.0125627825f, -0.00731058326f, + -0.00641087024f, 0.00111717137f, 0.0159491561f, 0.00795465801f, -0.0157765169f, + 0.0209025573f, 0.029614171f, -0.0261613969f, -0.00472100358f, 0.0126623819f, + -0.0205971207f, -0.0115933502f, -0.00456496468f, 0.0113808718f, 0.0070184255f, + 0.031393677f, 0.0195612889f, -0.00259787985f, -0.00527875917f, -0.0156968385f, + 0.0287376978f, -0.00298465695f, -0.0325091891f, -0.0180872194f, -0.0121776657f, + 0.0110023944f, 0.00835969485f, -0.0145282075f, -0.00673290761f, -0.00673954794f, + -0.0362275578f, 0.00117859081f, -0.0142758889f, -0.000151785076f, -0.00227252231f, + 0.00761602074f, 0.010643837f, -0.00766250072f, -0.0164803527f, 0.00324195484f, + -0.0177021027f, 0.00210486376f, 0.0224164668f, -0.00453176489f, -0.0338106193f, + -0.0260949973f, -0.0027240389f, 0.00402712869f, -0.0225625448f, 0.0192425698f, + -0.0300656874f, 0.0350323692f, 0.00645403005f, -0.0137978131f, 0.0107301567f, + 0.013591975f, 0.00509616034f, -0.0114472713f, 0.022642225f, 0.00324195484f, + 0.00457824441f, 0.0136118941f, 0.000350464776f, 0.0130275786f, 0.010902795f, + 0.0164936315f, 0.018153619f, -0.024421731f, -0.0309421606f, -0.0226555038f, + -0.0237046164f, 0.00681258691f, -0.00761602074f, 0.0134126963f, 0.0022675423f, + -0.0178083424f, -0.0187379345f, 0.0118921474f, 0.0076359408f, -0.0260949973f, + -0.00419312762f, 0.00595603371f, -0.000536175852f, -0.0189371333f, -0.00093291275f, + -0.169876441f, 0.00245180097f, 0.019136332f, -0.00802769791f, 0.0314999148f, + 0.00315065566f, 0.0112414332f, -0.0152851613f, 0.00383457029f, -0.00254144031f, + 0.0397865698f, -0.0223766267f, -0.0369977914f, -0.0131670181f, 0.0123104649f, + 0.000660674879f, -0.0206502397f, 0.0181137789f, 0.0116929496f, 0.0175161846f, + 0.0316592753f, -0.0146610066f, -0.0206502397f, 0.0160952359f, -0.0102321608f, + 0.00862529315f, 0.000525385898f, 0.0108231157f, -0.00460812403f, -0.0149930036f, + -0.0232796595f, -0.00348265306f, 0.0135255754f, 0.0291360933f, 0.00661670882f, + -0.00360549195f, -0.0122241452f, 0.00205838401f, -0.0103317602f, -0.0103782397f, + 0.0207963195f, -0.00966776535f, 0.0154179605f, -0.00599919353f, -0.00995328277f, + 0.0188707337f, 0.0345542915f, -0.0023854014f, 0.0158694778f, -0.0190566517f, + -0.0044985651f, -0.0328544639f, -0.0196542479f, -0.00234224182f, 0.0295876097f, + 0.0176489837f, 0.032323271f, -0.0163475536f, 0.00369513128f, -0.0118589476f, + 0.00875145197f, -0.00938224699f, 0.0110488739f, 0.00609879289f, -0.0149531644f, + -0.0163873937f, -0.0169982687f, 0.0157101173f, -0.0257497206f, 0.0157366786f, + -0.0343418121f, 0.00630795117f, 0.00132549973f, -0.00224928255f, 0.0170513876f, + 0.00206170394f, -0.0064175101f, -0.00396736944f, -0.0162413139f, -0.00283857808f, + 0.00229908223f, 0.0376352295f, -0.0113343922f, -0.00647394964f, 0.00522895949f, + 0.00646730978f, -0.00785505865f, -0.00471436325f, -0.00404372858f, -0.0226953439f, + 0.0032386349f, -0.0237842947f, 0.0051194001f, -0.0287908167f, 0.00190068525f, + 0.016374113f, 0.00686570676f, -0.00547795743f, -0.00899048988f, -0.0149531644f, + 0.0012117906f, 0.0159889963f, -0.00563067617f, 0.020862719f, 0.00715122465f, + 0.0053883181f, -0.0103981597f, 0.0116929496f, 0.0312343184f, -0.0110687939f, + -0.0220579095f, 0.00934240781f, 0.0112945521f, -0.00479072286f, 0.0110555142f, + 0.00756290136f, 0.01932225f, -0.0133595765f, 0.000450686493f, 0.00122673053f, + 0.0844601467f, 0.0145547669f, 0.0211283155f, 0.0243951716f, -0.0251388457f, + -0.029242333f, -0.111019939f, -0.00749650178f, -0.0111152735f, 0.0209689569f, + -0.0076359408f, 0.0298000891f, -0.00591951422f, 0.0145282075f, 0.00177120627f, + 0.00275889854f, 0.000104319814f, -0.0345808528f, -0.0155241992f, -0.0145813273f, + 0.0245014094f, 0.0104180789f, -0.00419312762f, -0.0212478358f, -0.00725746388f, + 0.0281799417f, -0.0216329526f, 0.0160288364f, 0.00370841124f, -0.0362010002f, + 0.0224164668f, 0.0127553409f, -0.0161085147f, 0.0177552216f, 0.0135255754f, + 0.0143954083f, 0.00340629346f, -0.00498660142f, 0.0243818909f, -0.00597927347f, + 0.00326851453f, -0.0137845334f, -0.0339434184f, -0.00417984743f, 0.0116464701f, + -0.0340496562f, 0.00460480433f, 0.0052920389f, 0.0100329621f, -0.0220579095f, + -0.00893737096f, 0.0070981048f, 0.00857881363f, 0.00189736532f, 0.0293751322f, + -0.0170912277f, -0.0216063932f, 0.00242690113f, -0.024660768f, -0.0096146455f, + 0.0108563155f, 0.0148867648f, 0.00144335884f, -0.00531859882f, -0.0362806767f, + 0.00548459729f, 0.00395076955f, 0.00950176641f, -0.0220579095f, 0.00802105758f, + -0.0145016471f, 0.0181403384f, -0.0063212309f, -0.000105720428f, 0.0226953439f, + -0.0160288364f, 0.016520191f, 0.0147141255f, -0.0192558505f, 0.0205041617f, + -0.0256302003f, 0.00835305545f, -0.0253114831f, -0.00532855885f, 0.0286048986f, + -0.0127619812f, 0.00752970157f, -0.0176091436f, 0.0115468707f, -0.00156868785f, + 0.0253911633f, 0.0197472069f, 0.00592283392f, -0.000907182985f, -0.0183129776f, + 0.0077952994f, -0.0110223144f, 0.0192956906f, 0.00390760973f, -0.0176755432f, + -0.0199729651f, 0.0389366597f, -0.0137048541f, 0.00368185132f, -0.0341824554f, + -0.00388768991f, -0.0296938494f, 0.0189636927f, -0.0524555929f, 0.0309421606f, + -0.00386112998f, 0.00865185261f, -0.0241826922f, 0.0186316948f, 0.0270245895f, + -0.00507624075f, -0.0129877394f, 0.0184324961f, 0.00382129033f, 0.0384851396f, + -0.0295079313f, 0.00613531237f, -0.0210353564f, 0.012516303f, 0.0177950617f, + -0.0138774924f, 0.0189371333f, -0.00636771042f, -0.000126574014f, -0.029056415f, + 0.00665986817f, -0.00294647715f, 0.000263522961f, -0.0198534466f, -0.00535511831f, + 0.0369446725f, -0.030225046f, -0.00420308718f, -0.0130142989f, -0.0264933947f, + -0.0226953439f, -0.0106106373f, -0.00508620031f, -0.013240057f, -0.0110621545f, + 0.0223899055f, 0.00990016293f, 0.0491090603f, -0.0238374155f, -0.0254310034f, + 0.00958808605f, -0.0114339916f, 0.0202784035f, 0.0168389101f, 0.0110488739f, + 0.00617847219f, 0.0166264307f, 0.00269581913f, 0.00739026256f, 0.0261348374f, + -0.0189105738f, -0.010902795f, -0.0131138982f, -0.0266527534f, 0.031818632f, + 0.0126225417f, 0.00265099946f, 0.0208892785f, -0.00455832481f, 0.0212611146f, + 0.0184590574f, 0.00597927347f, 0.00397400931f, -0.016281154f, 0.00729730353f, + 0.0107899159f, 0.0179278608f, -0.0358291604f, 0.00235054176f, -0.00723754382f, + -0.00348929293f, -0.00451848516f, -0.0250458848f, 0.00532523869f, 0.00425620703f, + 0.0079878578f, 0.000590125448f, 0.01548436f, -0.00934904721f, 0.00942872651f, + -0.0384851396f, 0.0121112661f, 0.0099665625f, 0.00859209336f, -0.0127221411f, + 0.00713130459f, -0.0103118401f, 0.000337184872f, 0.0013080698f, -0.000826673582f, + 0.00736370264f, -0.0185652953f, 0.000161848744f, 0.0133861359f, -0.00597595377f, + 0.00424956717f, 0.034952689f, 0.0338902958f, -0.000162263736f, 0.0100728022f, + -0.00863857288f, -0.0110621545f, 0.000502976123f, 0.00761602074f, -0.00870497245f, + 0.0134126963f, 0.00196542474f, 0.00656690914f, -0.00439564604f, 0.015391401f, + 0.0214337539f, 0.0284720995f, -0.00176456629f, 0.00932248775f, 0.0169717092f, + -0.0207564794f, -0.0272503477f, 0.00905688945f, 0.00983376335f, 0.000620420207f, + 0.0134790959f, -0.00633451063f, 0.00481728278f, 0.0129213398f, 0.014647726f, + 0.00096694252f, -0.00460148416f, 0.0157765169f, 0.00543811778f, 0.0158296376f, + -0.0359885208f, 0.00147821847f, -0.0258028395f, -0.0110090347f, -0.0223633461f, + 0.0167990699f, -0.0115003912f, 0.00705162529f, 0.00604899321f, -0.00887097139f, + 0.0017745262f, -0.0214603133f, 0.0415395163f, 0.00866513234f, -0.00297801686f, + -0.0149398837f, -0.0185652953f, 0.014647726f, 0.0138907721f, -0.00124499039f, + 0.0171310678f, -0.00336479396f, 0.0158030782f, -0.0135654146f, 0.00277715852f, + 0.0011130214f, 0.00737034297f, 0.0229211021f, 0.00273731886f, -0.000847423449f, + 0.00276553864f, -0.0142094893f, -0.0248334073f, -0.00493016187f, 0.0069387462f, + -0.0224563051f, -0.0243420508f, 0.0176224224f, 0.0113808718f, -0.0127487015f, + -0.0202784035f, -0.00921624806f, 0.00799449813f, 0.0174232256f, -0.0115402304f, + 0.0167061109f, -0.000982712372f, -0.0122175049f, 0.0237710159f, -0.0221110284f, + -0.021619672f, -0.00411344785f, -0.0155640393f, 0.000650299946f, 0.00979392417f, + -0.0121311862f + ]; + + var options = new VectorSearchOptions() + { + Filter = Builders.Filter.Eq(m => m.Plot.Rating, 5) + & Builders.Filter.Gt("year", 1900), + IndexName = nestedVectorIndexName, + ReturnStoredSource = true, + EmbeddedScoreMode = SearchScoreFunction.Average + }; + + var results = nestedVectorCollection + .Aggregate() + .VectorSearch(m => m.Plot.PlotEmbedding, vector, 1, options) + .Project(Builders.Projection + .Include(m => m.Title) + .MetaVectorSearchScore(p => p.Score)) + .ToList(); + + results.Count.Should().Be(1); + results[0].Title.Should().Be("The Charge of the Light Brigade"); + results.Should().OnlyContain(m => m.Score > 0.9); + } + private IMongoCollection GetEmbeddedMoviesCollection() => _mongoClient .GetDatabase("sample_mflix") .GetCollection("embedded_movies"); @@ -162,5 +1176,49 @@ public class BinaryVectorSearchItem [BsonElement("vectorSearchScore")] public double Score { get; set; } } + + [BsonIgnoreExtraElements] + public class MovieWithPlot + { + [BsonElement("title")] + public string Title { get; set; } + + [BsonElement("year")] + public int Year { get; set; } + + [BsonElement("available")] + public bool Available { get; set; } + + [BsonElement("score")] + public double Score { get; set; } + + [BsonElement("plot")] + public NestedPlot Plot { get; set; } + } + + public class NestedPlot + { + [BsonElement("plot")] + public string Plot { get; set; } + + [BsonElement("rating")] + public int Rating { get; set; } + + [BsonElement("plot-embedding")] + public float[] PlotEmbedding { get; set; } + } + + private static string GetRandomName() => $"test_{Guid.NewGuid():N}"; + + private bool TryGetIndex( + IMongoCollection collection, string indexName, out BsonDocument indexDefinition) + { + indexDefinition = collection.SearchIndexes.List().ToList() + .SingleOrDefault(i => i["name"].AsString == indexName)?.AsBsonDocument; + + return indexDefinition != null; + } + + private void SkipTests() => throw new SkipException("Test skipped because of CSHARP-5840; Atlas does not currently support these features."); } } From f970653011817e3c9ea14f98618c08fab6063ce9 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 17 Mar 2026 10:17:30 +0000 Subject: [PATCH 4/5] Updates following code review. --- .../CreateVectorSearchIndexModelBase.cs | 14 +++++++---- .../PipelineStageDefinitionBuilder.cs | 8 ++++++- .../PipelineDefinitionBuilderTests.cs | 23 +++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs index 26912631021..b50aee1857f 100644 --- a/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs +++ b/src/MongoDB.Driver/CreateVectorSearchIndexModelBase.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Linq; using MongoDB.Bson; +using MongoDB.Driver.Core.Misc; namespace MongoDB.Driver; @@ -86,6 +87,8 @@ protected CreateVectorSearchIndexModelBase( params FieldDefinition[] filterFields) : base(name, SearchIndexType.VectorSearch) { + Ensure.IsNotNull(field, nameof(field)); + Field = field; FilterFields = filterFields?.ToList() ?? []; } @@ -152,11 +155,12 @@ private protected void RenderCommonElements(RenderArgs renderArgs, Bs /// The field document into which the elements will go. private protected void RenderCommonFieldElements(RenderArgs renderArgs, BsonDocument fieldDocument) { - var quantizationValue = Quantization == VectorQuantization.BinaryNoRescore - ? "binaryNoRescore" - : Quantization?.ToString().ToLowerInvariant(); - - fieldDocument.Add("quantization", quantizationValue, quantizationValue != null); + if (Quantization != null && Quantization != VectorQuantization.None) + { + fieldDocument.Add("quantization", Quantization == VectorQuantization.BinaryNoRescore + ? "binaryNoRescore" + : Quantization.ToString().ToLowerInvariant()); + } if (HnswMaxEdges != null || HnswNumEdgeCandidates != null) { diff --git a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs index 95aa5a548c2..6771f15ed98 100644 --- a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs @@ -2183,8 +2183,14 @@ public static PipelineStageDefinition VectorSearch( { "returnStoredSource", true, options?.ReturnStoredSource == true }, }; - if (nestedRoot != null && options?.NestedFilter != null) + if (options?.NestedFilter != null) { + if (nestedRoot == null) + { + throw new InvalidOperationException( + $"A nested filter was specified for the search against field '{path}', but the field is not nested. Nested filters can only be used when searching against vectors in nested (embedded) documents."); + } + vectorSearchOperator.Add("filter", options.NestedFilter.Render( (args with { SubPathRoot = nestedRoot }) with { RenderDollarForm = true })); } diff --git a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs index d04392dbbf9..503ba22f8aa 100644 --- a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs @@ -707,6 +707,7 @@ private class MovieWithPlot { public int Year { get; set; } public NestedPlot Plot { get; set; } + public float[] NonNestedEmbedding { get; set; } } private class NestedPlot @@ -738,6 +739,28 @@ public void VectorSearch_should_throw_when_filter_is_at_wrong_level([Values(fals .Which.Message.Should().Contain("The field 'Year' is not part of the nested document 'Plot', which is the root of this search."); } + [Theory] + [ParameterAttributeData] + public void VectorSearch_should_throw_when_nested_filter_is_used_without_nesting([Values(false, true)] bool expressions) + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + }; + + options.NestedFilter = expressions + ? Builders.Filter.Lt(m => m.Plot.Rating, 1900) + : Builders.Filter.Lt("Plot.Rating", 1900); + + var result = pipeline.VectorSearch(m => m.NonNestedEmbedding, new[] { 1.0, 2.0, 3.0 }, 1, options); + + var exception = Record.Exception(() => RenderStages(result, BsonSerializer.SerializerRegistry.GetSerializer())); + + exception.Should().BeOfType() + .Which.Message.Should().Contain("A nested filter was specified for the search against field 'NonNestedEmbedding',"); + } + [Fact] public void VectorSearch_should_throw_when_pipeline_is_null() { From bfec61acb5ddd28c6fbf28d3794c9bc0efbe9406 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Fri, 20 Mar 2026 10:35:30 +0000 Subject: [PATCH 5/5] Add check for using embedded score on non-nested search --- .../PipelineStageDefinitionBuilder.cs | 6 +++++ .../PipelineDefinitionBuilderTests.cs | 22 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs index 6771f15ed98..3e43bb5406e 100644 --- a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs @@ -2197,6 +2197,12 @@ public static PipelineStageDefinition VectorSearch( if (options?.EmbeddedScoreMode != null) { + if (nestedRoot == null) + { + throw new InvalidOperationException( + $"The option '{nameof(VectorSearchOptions.EmbeddedScoreMode)}' was set for the search against field '{path}', but the field is not nested. Embedded score mode can only be used when searching against vectors in nested (embedded) documents."); + } + vectorSearchOperator.Add("nestedOptions", new BsonDocument { { "scoreMode", options.EmbeddedScoreMode == SearchScoreFunction.Average ? "avg" : "max" } diff --git a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs index 503ba22f8aa..6857a73faa4 100644 --- a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs @@ -668,10 +668,10 @@ public void VectorSearch_should_add_expected_stage_with_nested_options() IndexName = "index_name", EmbeddedScoreMode = SearchScoreFunction.Average, }; - var result = pipeline.VectorSearch("x", new[] { 1.0, 2.0, 3.0 }, 1, options); + var result = pipeline.VectorSearch("x.y", new[] { 1.0, 2.0, 3.0 }, 1, options); var stages = RenderStages(result, BsonDocumentSerializer.Instance); - stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x', limit: 1, numCandidates: 10, index: 'index_name', nestedOptions: { scoreMode: 'avg' } } }"); + stages[0].Should().BeEquivalentTo("{ $vectorSearch: { queryVector: [1.0, 2.0, 3.0], path: 'x.y', limit: 1, numCandidates: 10, index: 'index_name', nestedOptions: { scoreMode: 'avg' } } }"); } [Theory] @@ -761,6 +761,24 @@ public void VectorSearch_should_throw_when_nested_filter_is_used_without_nesting .Which.Message.Should().Contain("A nested filter was specified for the search against field 'NonNestedEmbedding',"); } + [Fact] + public void VectorSearch_should_throw_when_embedded_score_is_used_without_nesting() + { + var pipeline = new EmptyPipelineDefinition(); + var options = new VectorSearchOptions() + { + IndexName = "index_name", + EmbeddedScoreMode = SearchScoreFunction.Average, + }; + + var result = pipeline.VectorSearch(m => m.NonNestedEmbedding, new[] { 1.0, 2.0, 3.0 }, 1, options); + + var exception = Record.Exception(() => RenderStages(result, BsonSerializer.SerializerRegistry.GetSerializer())); + + exception.Should().BeOfType() + .Which.Message.Should().Contain("The option 'EmbeddedScoreMode' was set for the search against field 'NonNestedEmbedding', but the field is not nested."); + } + [Fact] public void VectorSearch_should_throw_when_pipeline_is_null() {