diff --git a/Directory.Packages.props b/Directory.Packages.props
index bb90845f3f8..a367f152413 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -37,7 +37,7 @@
-
+
diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs
index 50068ca74ba..723c8206a38 100644
--- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs
+++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs
@@ -80,12 +80,14 @@ protected override Expression VisitExtension(Expression expression)
}
// Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2))
+ // we do this for FullTextContainsAll, FullTextContainsAny and FullTextScore
case SqlFunctionExpression
{
- Name: "FullTextContainsAny" or "FullTextContainsAll",
+ Name: string name,
+ IsScoringFunction: bool scoringFunction,
Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: var elementTypeMapping }, Type: Type type } keywords]
} fullTextContainsAllAnyFunction
- when type == typeof(string[]):
+ when (name is "FullTextContainsAny" or "FullTextContainsAll" or "FullTextScore") && type == typeof(string[]):
{
var keywordValues = new List();
foreach (var value in (IEnumerable)parametersValues[keywords.Name])
@@ -93,35 +95,14 @@ protected override Expression VisitExtension(Expression expression)
keywordValues.Add(sqlExpressionFactory.Constant(value, typeof(string), elementTypeMapping));
}
- return sqlExpressionFactory.Function(
+ return new SqlFunctionExpression(
fullTextContainsAllAnyFunction.Name,
+ scoringFunction,
[property, .. keywordValues],
fullTextContainsAllAnyFunction.Type,
fullTextContainsAllAnyFunction.TypeMapping);
}
- // Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2]))
- case SqlFunctionExpression
- {
- Name: "FullTextScore",
- IsScoringFunction: true,
- Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: not null } typeMapping } keywords]
- } fullTextScoreFunction:
- {
- var keywordValues = new List();
- foreach (var value in (IEnumerable)parametersValues[keywords.Name])
- {
- keywordValues.Add((string)value);
- }
-
- return new SqlFunctionExpression(
- fullTextScoreFunction.Name,
- scoringFunction: true,
- [property, sqlExpressionFactory.Constant(keywordValues, typeMapping)],
- fullTextScoreFunction.Type,
- fullTextScoreFunction.TypeMapping);
- }
-
default:
return expression;
}
diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs
index b7de73b0257..7331a1878ff 100644
--- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs
+++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs
@@ -41,12 +41,25 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF
typeMappingSource.FindMapping(typeof(bool))),
nameof(CosmosDbFunctionsExtensions.FullTextScore)
- when arguments is [_, var property, var keywords] => sqlExpressionFactory.ScoringFunction(
+ when arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords]
+ && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction(
+ "FullTextScore",
+ [property, .. values.Select(x => sqlExpressionFactory.Constant(x))],
+ typeof(double),
+ typeMappingSource.FindMapping(typeof(double))),
+
+ nameof(CosmosDbFunctionsExtensions.FullTextScore)
+ when arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords]
+ && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction(
+ "FullTextScore",
+ [property, keywords],
+ typeof(double),
+ typeMappingSource.FindMapping(typeof(double))),
+
+ nameof(CosmosDbFunctionsExtensions.FullTextScore)
+ when arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => sqlExpressionFactory.ScoringFunction(
"FullTextScore",
- [
- property,
- keywords,
- ],
+ [property, .. keywords.Items],
typeof(double),
typeMappingSource.FindMapping(typeof(double))),
diff --git a/test/EFCore.Cosmos.FunctionalTests/FullTextSearchCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/FullTextSearchCosmosTest.cs
index b74d601792b..1e99de310ce 100644
--- a/test/EFCore.Cosmos.FunctionalTests/FullTextSearchCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/FullTextSearchCosmosTest.cs
@@ -292,7 +292,7 @@ public virtual async Task OrderByRank_FullTextScore_constant()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter"])
+ORDER BY RANK FullTextScore(c["Description"], "otter")
""");
}
@@ -309,7 +309,7 @@ public virtual async Task OrderByRank_FullTextScore_constants()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter","beaver"])
+ORDER BY RANK FullTextScore(c["Description"], "otter", "beaver")
""");
}
@@ -326,7 +326,7 @@ public virtual async Task OrderByRank_FullTextScore_constant_array()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter","beaver"])
+ORDER BY RANK FullTextScore(c["Description"], "otter", "beaver")
""");
}
@@ -343,7 +343,7 @@ public virtual async Task OrderByRank_FullTextScore_constant_array_with_one_elem
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter"])
+ORDER BY RANK FullTextScore(c["Description"], "otter")
""");
}
@@ -361,7 +361,7 @@ public virtual async Task OrderByRank_FullTextScore_parameter_array()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter","beaver"])
+ORDER BY RANK FullTextScore(c["Description"], "otter", "beaver")
""");
}
@@ -384,7 +384,7 @@ public virtual async Task OrderByRank_FullTextScore_using_parameters()
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], [@otter, @beaver])
+ORDER BY RANK FullTextScore(c["Description"], @otter, @beaver)
""");
}
@@ -405,7 +405,7 @@ public virtual async Task OrderByRank_FullTextScore_using_one_parameter()
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], [@otter])
+ORDER BY RANK FullTextScore(c["Description"], @otter)
""");
}
@@ -426,7 +426,28 @@ public virtual async Task OrderByRank_FullTextScore_using_parameters_constant_mi
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["otter", @beaver])
+ORDER BY RANK FullTextScore(c["Description"], "otter", @beaver)
+""");
+ }
+
+ [ConditionalFact]
+ public virtual async Task OrderByRank_FullTextScore_using_parameters_constant_mix_inline()
+ {
+ await using var context = CreateContext();
+
+ var beaver = "beaver";
+
+ var result = await context.Set()
+ .OrderBy(x => EF.Functions.FullTextScore(x.Description, "otter", beaver))
+ .ToListAsync();
+
+ AssertSql(
+"""
+@beaver='beaver'
+
+SELECT VALUE c
+FROM root c
+ORDER BY RANK FullTextScore(c["Description"], "otter", @beaver)
""");
}
@@ -447,7 +468,7 @@ public virtual async Task OrderByRank_FullTextScore_using_parameter()
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], [@otter])
+ORDER BY RANK FullTextScore(c["Description"], @otter)
""");
}
@@ -464,7 +485,7 @@ public virtual async Task OrderByRank_FullTextScore_using_complex_expression()
.ToListAsync())).Message;
Assert.Contains(
- "The second argument of the FullTextScore function must be a non-empty array of string literals.",
+ "The second through last arguments of the FullTextScore function must be string literals.",
message);
}
@@ -495,7 +516,7 @@ public virtual async Task OrderByRank_FullTextScore_on_non_FTS_property()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["PartitionKey"], ["taxonomy"])
+ORDER BY RANK FullTextScore(c["PartitionKey"], "taxonomy")
""");
}
@@ -514,7 +535,7 @@ public virtual async Task OrderByRank_with_RRF_using_two_FullTextScore_functions
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK RRF(FullTextScore(c["Description"], ["beaver"]), FullTextScore(c["Description"], ["otter","bat"]))
+ORDER BY RANK RRF(FullTextScore(c["Description"], "beaver"), FullTextScore(c["Description"], "otter", "bat"))
""");
}
@@ -584,7 +605,7 @@ public virtual async Task OrderByRank_Take()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["beaver"])
+ORDER BY RANK FullTextScore(c["Description"], "beaver")
OFFSET 0 LIMIT 10
""");
}
@@ -603,7 +624,7 @@ public virtual async Task OrderByRank_Skip_Take()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Description"], "beaver", "dolphin")
OFFSET 1 LIMIT 20
""");
}
@@ -633,7 +654,7 @@ public virtual async Task OrderBy_scoring_function_overridden_by_another()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["beaver","dolphin","second"])
+ORDER BY RANK FullTextScore(c["Description"], "beaver", "dolphin", "second")
""");
}
@@ -667,7 +688,7 @@ public virtual async Task Regular_OrderBy_overridden_by_OrderBy_using_scoring_fu
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Description"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Description"], "beaver", "dolphin")
""");
}
@@ -725,7 +746,7 @@ public virtual async Task OrderByRank_Where()
SELECT VALUE c
FROM root c
WHERE ((c["PartitionKey"] || "Foo") = "habitatFoo")
-ORDER BY RANK FullTextScore(c["Description"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Description"], "beaver", "dolphin")
""");
}
@@ -779,7 +800,7 @@ public virtual async Task OrderByRank_with_FullTextScore_on_nested_owned_type()
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Owned"]["NestedReference"]["AnotherDescription"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Owned"]["NestedReference"]["AnotherDescription"], "beaver", "dolphin")
""");
}
@@ -816,7 +837,7 @@ public virtual async Task OrderByRank_with_FullTextScore_on_nested_owned_collect
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Owned"]["NestedCollection"][0]["AnotherDescription"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Owned"]["NestedCollection"][0]["AnotherDescription"], "beaver", "dolphin")
""");
}
@@ -832,7 +853,7 @@ public virtual async Task OrderBy_scoring_function_on_property_with_modified_jso
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["CustomDecription"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["CustomDecription"], "beaver", "dolphin")
""");
}
@@ -849,7 +870,7 @@ public virtual async Task OrderByRank_with_FullTextScore_on_nested_owned_type_wi
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["Owned"]["CustomNestedReference"]["AnotherDescription"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["Owned"]["CustomNestedReference"]["AnotherDescription"], "beaver", "dolphin")
""");
}
@@ -866,7 +887,7 @@ public virtual async Task OrderByRank_with_FullTextScore_on_property_without_ind
"""
SELECT VALUE c
FROM root c
-ORDER BY RANK FullTextScore(c["DescriptionNoIndex"], ["beaver","dolphin"])
+ORDER BY RANK FullTextScore(c["DescriptionNoIndex"], "beaver", "dolphin")
""");
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/HybridSearchCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/HybridSearchCosmosTest.cs
index 50007892eee..9aa78fbcfa4 100644
--- a/test/EFCore.Cosmos.FunctionalTests/HybridSearchCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/HybridSearchCosmosTest.cs
@@ -39,7 +39,7 @@ public virtual async Task Hybrid_search_vector_distance_and_FullTextScore_in_Ord
SELECT VALUE c
FROM root c
-ORDER BY RANK RRF(FullTextScore(c["Description"], ["beaver","otter"]), VectorDistance(c["SBytes"], @inputVector, false, {'distanceFunction':'dotproduct', 'dataType':'int8'}))
+ORDER BY RANK RRF(FullTextScore(c["Description"], "beaver", "otter"), VectorDistance(c["SBytes"], @inputVector, false, {'distanceFunction':'dotproduct', 'dataType':'int8'}))
""");
}
@@ -62,7 +62,7 @@ public virtual async Task Hybrid_search_vector_distance_and_FullTextScore_with_s
SELECT VALUE c
FROM root c
-ORDER BY RANK RRF(FullTextScore(c["Description"], ["beaver"]), VectorDistance(c["SBytes"], @inputVector, false, {'distanceFunction':'dotproduct', 'dataType':'int8'}))
+ORDER BY RANK RRF(FullTextScore(c["Description"], "beaver"), VectorDistance(c["SBytes"], @inputVector, false, {'distanceFunction':'dotproduct', 'dataType':'int8'}))
""");
}
@@ -84,7 +84,7 @@ public virtual async Task Hybrid_search_vector_distance_and_FullTextScore_in_Ord
SELECT VALUE c
FROM root c
-ORDER BY RANK RRF(FullTextScore(c["Owned"]["AnotherDescription"], ["beaver"]), VectorDistance(c["Owned"]["Singles"], @inputVector, false, {'distanceFunction':'cosine', 'dataType':'float32'}))
+ORDER BY RANK RRF(FullTextScore(c["Owned"]["AnotherDescription"], "beaver"), VectorDistance(c["Owned"]["Singles"], @inputVector, false, {'distanceFunction':'cosine', 'dataType':'float32'}))
""");
}
@@ -107,7 +107,7 @@ public virtual async Task Hybrid_search_vector_distance_and_FullTextScore_in_Ord
SELECT VALUE c
FROM root c
-ORDER BY RANK RRF(VectorDistance(c["Owned"]["Singles"], @inputVector, false, {'distanceFunction':'cosine', 'dataType':'float32'}), FullTextScore(c["Owned"]["AnotherDescription"], ["beaver","otter"]))
+ORDER BY RANK RRF(VectorDistance(c["Owned"]["Singles"], @inputVector, false, {'distanceFunction':'cosine', 'dataType':'float32'}), FullTextScore(c["Owned"]["AnotherDescription"], "beaver", "otter"))
""");
}