diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs index 7867846946..dafc1d7265 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs @@ -64,6 +64,7 @@ public static SqlScalarExpression VisitBuiltinFunctionCall(MethodCallExpression case nameof(CosmosLinqExtensions.DocumentId): case nameof(CosmosLinqExtensions.RRF): case nameof(CosmosLinqExtensions.FullTextScore): + case nameof(CosmosLinqExtensions.VectorDistance): return OtherBuiltinSystemFunctions.Visit(methodCallExpression, context); default: return TypeCheckFunctions.Visit(methodCallExpression, context); diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/OtherBuiltinSystemFunctions.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/OtherBuiltinSystemFunctions.cs index 09f218bd4a..a928f889e8 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/OtherBuiltinSystemFunctions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/OtherBuiltinSystemFunctions.cs @@ -10,6 +10,9 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.ObjectModel; using System.Globalization; using System.Linq.Expressions; + using System.Text.Json; + using System.Text.Json.Serialization; + using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.SqlObjects; internal static class OtherBuiltinSystemFunctions @@ -41,19 +44,22 @@ protected override SqlScalarExpression VisitImplicit(MethodCallExpression method throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, - "Expressions of type {0} is not supported as an argument to CosmosLinqExtensions.RRF. Supported expressions are method calls to {1}.", + "Expressions of type {0} is not supported as an argument to CosmosLinqExtensions.RRF. Supported expressions are method calls to {1}, {2}.", argument.Type, - nameof(CosmosLinqExtensions.FullTextScore))); + nameof(CosmosLinqExtensions.FullTextScore), + nameof(CosmosLinqExtensions.VectorDistance))); } - if (functionCallExpression.Method.Name != nameof(CosmosLinqExtensions.FullTextScore)) + if (functionCallExpression.Method.Name != nameof(CosmosLinqExtensions.FullTextScore) && + functionCallExpression.Method.Name != nameof(CosmosLinqExtensions.VectorDistance)) { throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, - "Method {0} is not supported as an argument to CosmosLinqExtensions.RRF. Supported methods are {1}.", + "Method {0} is not supported as an argument to CosmosLinqExtensions.RRF. Supported methods are {1}, {2}.", functionCallExpression.Method.Name, - nameof(CosmosLinqExtensions.FullTextScore))); + nameof(CosmosLinqExtensions.FullTextScore), + nameof(CosmosLinqExtensions.VectorDistance))); } arguments.Add(ExpressionToSql.VisitNonSubqueryScalarExpression(argument, context)); @@ -108,6 +114,55 @@ protected override SqlScalarExpression VisitExplicit(MethodCallExpression method } } + private class VectorDistanceVisit : SqlBuiltinFunctionVisitor + { + public VectorDistanceVisit() + : base("VectorDistance", + true, + new List() + { + new Type[]{typeof(float[]), typeof(float[]), typeof(bool), typeof(CosmosLinqExtensions.VectorDistanceOptions)}, + new Type[]{typeof(sbyte[]), typeof(sbyte[]), typeof(bool), typeof(CosmosLinqExtensions.VectorDistanceOptions)}, + new Type[]{typeof(byte[]), typeof(byte[]), typeof(bool), typeof(CosmosLinqExtensions.VectorDistanceOptions)}, + }) + { + } + + protected override SqlScalarExpression VisitImplicit(MethodCallExpression methodCallExpression, TranslationContext context) + { + if (methodCallExpression.Arguments.Count != 4) throw new ArgumentException(); + + List arguments = new List + { + ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[0], context), + ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[1], context), + ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[2], context) + }; + + if (methodCallExpression.Arguments[3] is ConstantExpression optionExpression && optionExpression.Value != null) + { + JsonSerializerOptions options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + + string serializedConstant = JsonSerializer.Serialize( + optionExpression.Value, + options); + + arguments.Add(CosmosElement.Parse(serializedConstant).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton)); + } + + return SqlFunctionCallScalarExpression.CreateBuiltin(SqlFunctionCallScalarExpression.Names.VectorDistance, arguments.ToImmutableArray()); + } + + protected override SqlScalarExpression VisitExplicit(MethodCallExpression methodCallExpression, TranslationContext context) + { + return null; + } + } + private static Dictionary FunctionsDefinitions { get; set; } static OtherBuiltinSystemFunctions() @@ -123,6 +178,7 @@ static OtherBuiltinSystemFunctions() }), [nameof(CosmosLinqExtensions.RRF)] = new RRFVisit(), [nameof(CosmosLinqExtensions.FullTextScore)] = new FullTextScoreVisit(), + [nameof(CosmosLinqExtensions.VectorDistance)] = new VectorDistanceVisit(), }; } diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs index b4ba33b323..56f05c9faa 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs @@ -5,13 +5,12 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; - using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; - using System.Runtime.CompilerServices; + using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Diagnostics; @@ -22,6 +21,33 @@ namespace Microsoft.Azure.Cosmos.Linq /// public static class CosmosLinqExtensions { + /// + /// Object representing the options for vector distance calculation. All field are optional. if a field is not specified, the default value will be used. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/vectordistance. + /// + public sealed class VectorDistanceOptions + { + /// + /// The metric used to compute distance/similarity. Valid values are "cosine", "dotproduct", "euclidean". + /// If not specified, the default value is what is defined in the container policy + /// + [JsonPropertyName("distanceFunction")] + public DistanceFunction? DistanceFunction { get; set; } + + /// + /// The data type of the vectors. float32, int8, uint8 values. Default value is float32. + /// + [JsonPropertyName("dataType")] + public VectorDataType? DataType { get; set; } + + /// + /// An integer specifying the size of the search list when conducting a vector search on the DiskANN index. + /// Increasing this may improve accuracy at the expense of RU cost and latency. Min=1, Default=10, Max=100. + /// + [JsonPropertyName("searchListSizeMultiplier")] + public int? SearchListSizeMultiplier { get; set; } + } + /// /// Returns the integer identifier corresponding to a specific item within a physical partition. /// This method is to be used in LINQ expressions only and will be evaluated on server. @@ -239,6 +265,75 @@ public static bool RegexMatch(this object obj, string regularExpression, string throw new NotImplementedException(ClientResources.ExtensionMethodNotImplemented); } + /// + /// Returns the similarity score between two specified vectors. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/vectordistance. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// The first vector. + /// The second vector. + /// A boolean specifying how the computed value is used in an ORDER BY expression. If true, then brute force is used. A value of false uses any index defined on the vector property, if it exists. + /// An JSON formatted object literal used to specify options for the vector distance calculation. + /// Returns the similarity score between two specified vectors. + /// + /// + /// document.vector1.VectorDistance(, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, DataType = VectorDataType.Float32})); + /// ]]> + /// + /// + public static double VectorDistance(this float[] vector1, float[] vector2, bool isBruteForce, VectorDistanceOptions options) + { + throw new NotImplementedException(ClientResources.ExtensionMethodNotImplemented); + } + + /// + /// Returns the similarity score between two specified vectors. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/vectordistance. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// The first vector. + /// The second vector. + /// A boolean specifying how the computed value is used in an ORDER BY expression. If true, then brute force is used. A value of false uses any index defined on the vector property, if it exists. + /// An JSON formatted object literal used to specify options for the vector distance calculation. + /// Returns the similarity score between two specified vectors. + /// + /// + /// document.vector1.VectorDistance(, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, DataType = VectorDataType.Int8})); + /// ]]> + /// + /// + public static double VectorDistance(this byte[] vector1, byte[] vector2, bool isBruteForce, VectorDistanceOptions options) + { + throw new NotImplementedException(ClientResources.ExtensionMethodNotImplemented); + } + + /// + /// Returns the similarity score between two specified vectors. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/vectordistance. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// The first vector. + /// The second vector. + /// A boolean specifying how the computed value is used in an ORDER BY expression. If true, then brute force is used. A value of false uses any index defined on the vector property, if it exists. + /// An JSON formatted object literal used to specify options for the vector distance calculation. + /// Returns the similarity score between two specified vectors. + /// + /// + /// document.vector1.VectorDistance(, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, DataType = VectorDataType.Uint8})); + /// ]]> + /// + /// + public static double VectorDistance(this sbyte[] vector1, sbyte[] vector2, bool isBruteForce, VectorDistanceOptions options) + { + throw new NotImplementedException(ClientResources.ExtensionMethodNotImplemented); + } + /// /// Returns a boolean indicating whether the keyword string expression is contained in a specified property path. /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/fulltextcontains. @@ -310,7 +405,7 @@ public static bool FullTextContainsAny(this object obj, params string[] searches /// /// /// A nonempty array of string literals. - /// Returns true BM25 score value that can only be used in an ORDER BY RANK clause. + /// Returns a BM25 score value that can only be used in an ORDER BY RANK clause. /// /// /// argu LambdaExpression lambda = Utilities.GetLambda(arguments[1]); SqlScalarExpression sqlfunc = ExpressionToSql.VisitScalarExpression(lambda, context); - SqlOrderByItem orderByItem = SqlOrderByItem.Create(sqlfunc, isDescending); + + // Order By VectorDistance is a special case, since there is no ordering required. + bool isVectorDistance = (sqlfunc is SqlFunctionCallScalarExpression functionCall) && (functionCall.Name.Value == SqlFunctionCallScalarExpression.Names.VectorDistance); + + SqlOrderByItem orderByItem = SqlOrderByItem.Create(sqlfunc, isVectorDistance ? null : isDescending); SqlOrderByClause orderby = SqlOrderByClause.Create(new SqlOrderByItem[] { orderByItem }); return orderby; } diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs index bae3995c8f..e234077850 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs @@ -376,7 +376,8 @@ public static class Names #pragma warning restore CS0108 // Member hides inherited member; missing new keyword public const string Trim = "TRIM"; public const string Trunc = "TRUNC"; - public const string Upper = "UPPER"; + public const string Upper = "UPPER"; + public const string VectorDistance = "VectorDistance"; } public static class Identifiers diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRRFOrderByRankFunction.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRRFOrderByRankFunction.xml index 57e4f43d6b..f13d85d4ed 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRRFOrderByRankFunction.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRRFOrderByRankFunction.xml @@ -77,7 +77,7 @@ WHERE (RRF(FullTextScore(root["StringField"], "test1"), FullTextScore(root["Stri - + @@ -87,7 +87,7 @@ WHERE (RRF(FullTextScore(root["StringField"], "test1"), FullTextScore(root["Stri - + @@ -97,7 +97,7 @@ WHERE (RRF(FullTextScore(root["StringField"], "test1"), FullTextScore(root["Stri - + @@ -107,7 +107,7 @@ WHERE (RRF(FullTextScore(root["StringField"], "test1"), FullTextScore(root["Stri - + @@ -117,7 +117,7 @@ WHERE (RRF(FullTextScore(root["StringField"], "test1"), FullTextScore(root["Stri - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestVectorDistanceFunction.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestVectorDistanceFunction.xml new file mode 100644 index 0000000000..48b99e5336 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestVectorDistanceFunction.xml @@ -0,0 +1,605 @@ + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null))]]> + + + + + + + + + + (doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null) > 0)).Select(doc => doc.Pk)]]> + + + 0)]]> + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null), (key, values) => key)]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(Cosine, Nullable`1), DataType = Convert(Float32, Nullable`1), SearchListSizeMultiplier = Convert(20, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(Cosine, Nullable`1), DataType = Convert(Float32, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(Cosine, Nullable`1), SearchListSizeMultiplier = Convert(10, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DataType = Convert(Float32, Nullable`1), SearchListSizeMultiplier = Convert(10, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions()))]]> + + + + + + + + + + RRF(new [] {doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorFloatField.VectorDistance(new [] {3, 4, 5}, False, null)})).Select(doc => doc.Pk)]]> + + + + + + + + + + RRF(new [] {doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorFloatField.FullTextScore(new [] {"string", "name"})})).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null))]]> + + + + + + + + + + (doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null) > 0)).Select(doc => doc.Pk)]]> + + + 0)]]> + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), (key, values) => key)]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(DotProduct, Nullable`1), DataType = Convert(Uint8, Nullable`1), SearchListSizeMultiplier = Convert(20, Nullable`1)}))]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DataType = Convert(Uint8, Nullable`1), SearchListSizeMultiplier = Convert(20, Nullable`1)}))]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(DotProduct, Nullable`1), DataType = Convert(Uint8, Nullable`1)}))]]> + + + + + + + + + + doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DataType = Convert(Uint8, Nullable`1)}))]]> + + + + + + + + + + RRF(new [] {doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorUInt8Field.VectorDistance(new [] {3, 4, 5}, False, null)})).Select(doc => doc.Pk)]]> + + + + + + + + + + RRF(new [] {doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorUInt8Field.VectorDistance(new [] {3, 4, 5}, False, new VectorDistanceOptions() {DistanceFunction = Convert(DotProduct, Nullable`1), DataType = Convert(Uint8, Nullable`1)})})).Select(doc => doc.Pk)]]> + + + + + + + + + + RRF(new [] {doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorUInt8Field.FullTextScore(new [] {"string", "name"})})).Select(doc => doc.Pk)]]> + + + + + + + + + + RRF(new [] {doc.VectorUInt8Field.VectorDistance(new [] {2, 3, 4}, False, new VectorDistanceOptions() {DataType = Convert(Uint8, Nullable`1), SearchListSizeMultiplier = Convert(20, Nullable`1)}), doc.VectorUInt8Field.FullTextScore(new [] {"string", "name"})})).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null)).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null))]]> + + + + + + + + + + (doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null) > 0)).Select(doc => doc.Pk)]]> + + + 0)]]> + + + + + + + doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), (key, values) => key)]]> + + + + + + + + + + doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(Euclidean, Nullable`1), DataType = Convert(Int8, Nullable`1)}))]]> + + + + + + + + + + RRF(new [] {doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorInt8Field.VectorDistance(new [] {3, 4, 5}, False, null)})).Select(doc => doc.Pk)]]> + + + + + + + + + + RRF(new [] {doc.VectorInt8Field.VectorDistance(new [] {2, 3, 4}, False, null), doc.VectorInt8Field.FullTextScore(new [] {"string", "name"})})).Select(doc => doc.Pk)]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, null))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DataType = Convert(Float32, Nullable`1), DistanceFunction = Convert(Euclidean, Nullable`1), SearchListSizeMultiplier = Convert(10, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DataType = null, DistanceFunction = null, SearchListSizeMultiplier = null}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {DistanceFunction = Convert(Euclidean, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {SearchListSizeMultiplier = Convert(1, Nullable`1)}))]]> + + + + + + + + + + doc.VectorFloatField.VectorDistance(new [] {2, 3, 4}, True, new VectorDistanceOptions() {SearchListSizeMultiplier = Convert(-100, Nullable`1)}))]]> + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs index c88b9e4418..85242ef652 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs @@ -112,7 +112,10 @@ internal class DataObject : LinqTestObject public double IntField; public string StringField; public string StringField2; - public int[] ArrayField; + public int[] ArrayField; + public float[] VectorFloatField; + public byte[] VectorInt8Field; + public sbyte[] VectorUInt8Field; public List EnumerableField; public Point Point; public int? NullableField; @@ -390,6 +393,157 @@ public void TestFullTextContainsFunction() }; this.ExecuteTestSuite(inputs); } + + [TestMethod] + public void TestVectorDistanceFunction() + { + const int Records = 2; + const int MaxStringLength = 100; + static DataObject createDataObj(Random random) + { + DataObject obj = new DataObject + { + StringField = LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)), + Id = Guid.NewGuid().ToString(), + VectorUInt8Field = new sbyte[] {1, 2, 3}, + VectorInt8Field = new byte[] { 1, 2, 3 }, + VectorFloatField = new float[] { 1, 2.0f, 3.0f }, + Pk = "Test" + }; + return obj; + } + Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, testContainer); + + List inputs = new List + { + new LinqTestInput("Float VectorDistance + Order By Rank", b => getQuery(b) + .OrderByRank(doc => doc.VectorFloatField.VectorDistance(new float[] {2,3,4}, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("Float VectorDistance + Order By", b => getQuery(b) + .OrderBy(doc => doc.VectorFloatField.VectorDistance(new float[] {2,3,4}, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("Float VectorDistance + Select", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] {2,3,4}, false, null))), + new LinqTestInput("Float VectorDistance + Where", b => getQuery(b) + .Where(doc => doc.VectorFloatField.VectorDistance(new float[] {2,3,4}, false, null) > 0) + .Select(doc => doc.Pk)), + new LinqTestInput("Float VectorDistance + GroupBy", b => getQuery(b) + .GroupBy(doc => doc.VectorFloatField.VectorDistance(new float[] {2,3,4}, false, null), (key, values) => key)), + new LinqTestInput("Float VectorDistance with non null fourth option", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, DataType = VectorDataType.Float32, SearchListSizeMultiplier = 20}))), + new LinqTestInput("Float VectorDistance with non null fourth option with default SearchListSizeMultiplier", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, DataType = VectorDataType.Float32}))), + new LinqTestInput("Float VectorDistance with non null fourth option with default DataType", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Cosine, SearchListSizeMultiplier = 10}))), + new LinqTestInput("Float VectorDistance with non null fourth option with default DistanceFunction", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DataType = VectorDataType.Float32, SearchListSizeMultiplier = 10}))), + new LinqTestInput("Float VectorDistance with non null fourth option with all default values", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions()))), + new LinqTestInput("Float VectorDistance + RRF", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, false, null), + doc.VectorFloatField.VectorDistance(new float[] { 3, 4, 5 }, false, null))) + .Select(doc => doc.Pk)), + new LinqTestInput("Float VectorDistance + RRF + FullTextScore", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, false, null), + doc.VectorFloatField.FullTextScore("string", "name"))) + .Select(doc => doc.Pk)), + + new LinqTestInput("UInt8 VectorDistance + Order By Rank", b => getQuery(b) + .OrderByRank(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + Order By", b => getQuery(b) + .OrderBy(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + Select", b => getQuery(b) + .Select(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null))), + new LinqTestInput("UInt8 VectorDistance + Where", b => getQuery(b) + .Where(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null) > 0) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + GroupBy", b => getQuery(b) + .GroupBy(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null), (key, values) => key)), + new LinqTestInput("UInt8 VectorDistance with non null fourth option", b => getQuery(b) + .Select(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.DotProduct, DataType = VectorDataType.Uint8, SearchListSizeMultiplier = 20 }))), + new LinqTestInput("UInt8 VectorDistance with non null fourth option with default DistanceFunction", b => getQuery(b) + .Select(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DataType = VectorDataType.Uint8, SearchListSizeMultiplier = 20 }))), + new LinqTestInput("UInt8 VectorDistance with non null fourth option with default SearchListSizeMultiplier", b => getQuery(b) + .Select(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.DotProduct, DataType = VectorDataType.Uint8 }))), + new LinqTestInput("UInt8 VectorDistance with non null fourth option with default DistanceFunction and SearchListSizeMultiplier", b => getQuery(b) + .Select(doc => doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DataType = VectorDataType.Uint8 }))), + new LinqTestInput("UInt8 VectorDistance + RRF", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null), + doc.VectorUInt8Field.VectorDistance(new sbyte[] { 3, 4, 5 }, false, null))) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + RRF + non null fourth option with default SearchListSizeMultiplier", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null), + doc.VectorUInt8Field.VectorDistance(new sbyte[] { 3, 4, 5 }, false, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.DotProduct, DataType = VectorDataType.Uint8 }))) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + RRF + FullTextScore", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, null), + doc.VectorUInt8Field.FullTextScore("string", "name"))) + .Select(doc => doc.Pk)), + new LinqTestInput("UInt8 VectorDistance + RRF + FullTextScore + non null fourth option with default DistanceFunction", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorUInt8Field.VectorDistance(new sbyte[] { 2, 3, 4 }, false, new VectorDistanceOptions() { DataType = VectorDataType.Uint8, SearchListSizeMultiplier = 20 }), + doc.VectorUInt8Field.FullTextScore("string", "name"))) + .Select(doc => doc.Pk)), + + new LinqTestInput("Int8 VectorDistance + Order By Rank", b => getQuery(b) + .OrderByRank(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("Int8 VectorDistance + Order By", b => getQuery(b) + .OrderBy(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null)) + .Select(doc => doc.Pk)), + new LinqTestInput("Int8 VectorDistance + Select", b => getQuery(b) + .Select(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null))), + new LinqTestInput("Int8 VectorDistance + Where", b => getQuery(b) + .Where(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null) > 0) + .Select(doc => doc.Pk)), + new LinqTestInput("Int8 VectorDistance + GroupBy", b => getQuery(b) + .GroupBy(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null), (key, values) => key)), + new LinqTestInput("Int8 VectorDistance with non null fourth option", b => getQuery(b) + .Select(doc => doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Euclidean, DataType = VectorDataType.Int8}))), + new LinqTestInput("Int8 VectorDistance + RRF", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null), + doc.VectorInt8Field.VectorDistance(new byte[] { 3, 4, 5 }, false, null))) + .Select(doc => doc.Pk)), + new LinqTestInput("Int8 VectorDistance + RRF + FullTextScore", b => getQuery(b) + .OrderByRank(doc => RRF(doc.VectorInt8Field.VectorDistance(new byte[] { 2, 3, 4 }, false, null), + doc.VectorInt8Field.FullTextScore("string", "name"))) + .Select(doc => doc.Pk)), + + // Other cases regarding fourth option + new LinqTestInput("VectorDistance with empty object", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions{}))), + new LinqTestInput("VectorDistance with empty object 2", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, null))), + new LinqTestInput("VectorDistance with default values", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions { DataType = VectorDataType.Float32, DistanceFunction = DistanceFunction.Euclidean, SearchListSizeMultiplier = 10 }))), + // ISSUE-TODO-leminh - the following two variations produce different results in the official run. + // new LinqTestInput("VectorDistance with non default values 1", b => getQuery(b) + // .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions { DataType = VectorDataType.// Int8, DistanceFunction = DistanceFunction.Cosine, SearchListSizeMultiplier = 20 }))), + // new LinqTestInput("VectorDistance with non default values 2", b => getQuery(b) + // .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions { DataType = VectorDataType.Uint8, DistanceFunction = DistanceFunction.DotProduct, SearchListSizeMultiplier = 50 }))), + new LinqTestInput("VectorDistance with nullable values", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions { DataType = null, DistanceFunction = null, SearchListSizeMultiplier = null }))), + new LinqTestInput("VectorDistance with partial fourth option", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { DistanceFunction = DistanceFunction.Euclidean }))), + new LinqTestInput("VectorDistance with partial fourth option 2", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { SearchListSizeMultiplier = 1 }))), + + // Negative case + new LinqTestInput("VectorDistance with fourth option with invalid values 1", b => getQuery(b) + .Select(doc => doc.VectorFloatField.VectorDistance(new float[] { 2, 3, 4 }, true, new VectorDistanceOptions() { SearchListSizeMultiplier = -100 }))) + }; + + foreach (LinqTestInput input in inputs) + { + // VectorDistance are not supported client side. + // Therefore this method is verified with baseline only. + input.skipVerification = true; + input.serializeOutput = true; + } + + this.ExecuteTestSuite(inputs); + } [TestMethod] public void TestFullTextScoreOrderByRankFunction() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 44ee444d5b..36bab4a278 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -244,6 +244,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 799b925fd6..16796b74e9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6361,6 +6361,27 @@ "Attributes": [], "MethodInfo": "Double RRF(Double[]);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Double VectorDistance(Byte[], Byte[], Boolean, VectorDistanceOptions)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Double VectorDistance(Byte[], Byte[], Boolean, VectorDistanceOptions);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double VectorDistance(SByte[], SByte[], Boolean, VectorDistanceOptions)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Double VectorDistance(SByte[], SByte[], Boolean, VectorDistanceOptions);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double VectorDistance(Single[], Single[], Boolean, VectorDistanceOptions)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Double VectorDistance(Single[], Single[], Boolean, VectorDistanceOptions);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Int32 DocumentId(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ @@ -6382,6 +6403,11 @@ ], "MethodInfo": "Microsoft.Azure.Cosmos.FeedIterator`1[T] ToFeedIterator[T](System.Linq.IQueryable`1[T]);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:True;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions+VectorDistanceOptions": { + "Type": "NestedType", + "Attributes": [], + "MethodInfo": null + }, "Microsoft.Azure.Cosmos.QueryDefinition ToQueryDefinition[T](System.Linq.IQueryable`1[T])[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ @@ -6558,6 +6584,155 @@ "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Response`1[TSource]] MinAsync[TSource](System.Linq.IQueryable`1[TSource], System.Threading.CancellationToken);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:True;IsConstructor:False;IsFinal:False;" } }, + "NestedTypes": { + "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions+VectorDistanceOptions;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] DistanceFunction[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"distanceFunction\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] DistanceFunction;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] DataType[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"dataType\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] DataType;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_SearchListSizeMultiplier()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_SearchListSizeMultiplier();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] SearchListSizeMultiplier[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"searchListSizeMultiplier\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] SearchListSizeMultiplier;CanRead:True;CanWrite:True;System.Nullable`1[System.Int32] get_SearchListSizeMultiplier();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + } + }, + "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions+VectorDistanceOptions;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:True;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] DistanceFunction[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"distanceFunction\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] DistanceFunction;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction] get_DistanceFunction();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] DataType[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"dataType\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] DataType;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType] get_DataType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_SearchListSizeMultiplier()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_SearchListSizeMultiplier();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] SearchListSizeMultiplier[System.Text.Json.Serialization.JsonPropertyNameAttribute(\"searchListSizeMultiplier\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyNameAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] SearchListSizeMultiplier;CanRead:True;CanWrite:True;System.Nullable`1[System.Int32] get_SearchListSizeMultiplier();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DataType(System.Nullable`1[Microsoft.Azure.Cosmos.VectorDataType]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DistanceFunction(System.Nullable`1[Microsoft.Azure.Cosmos.DistanceFunction]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_SearchListSizeMultiplier(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, "NestedTypes": {} }, "Microsoft.Azure.Cosmos.OperationKind;System.Enum;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:True;IsClass:False;IsValueType:True;IsNested:False;IsGenericType:False;IsSerializable:True": {