Skip to content

Commit d0237c7

Browse files
authored
[automated] Merge branch 'release/9.0' => 'main' (#35932)
2 parents 059c5c2 + ceb845a commit d0237c7

File tree

11 files changed

+87
-19
lines changed

11 files changed

+87
-19
lines changed

src/EFCore.Cosmos/EFCore.Cosmos.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Description>Azure Cosmos provider for Entity Framework Core.</Description>
@@ -12,6 +12,7 @@
1212
<NoWarn>$(NoWarn);EF9101</NoWarn> <!-- Metrics is experimental -->
1313
<NoWarn>$(NoWarn);EF9102</NoWarn> <!-- Paging is experimental -->
1414
<NoWarn>$(NoWarn);EF9103</NoWarn> <!-- Vector search is experimental -->
15+
<NoWarn>$(NoWarn);EF9104</NoWarn> <!-- Full-text search is experimental -->
1516
</PropertyGroup>
1617

1718
<ItemGroup>
@@ -49,7 +50,8 @@
4950

5051
<ItemGroup>
5152
<PackageReference Include="Microsoft.Azure.Cosmos" />
52-
<PackageReference Include="Newtonsoft.JSON" />
53+
<!-- Microsoft.Azure.Cosmos requires explicit reference to Newtonsoft.Json >= 10.0.2 -->
54+
<PackageReference Include="Newtonsoft.Json" />
5355
</ItemGroup>
5456

5557
<ItemGroup>

src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static T CoalesceUndefined<T>(
5959
/// <param name="property">The property to search.</param>
6060
/// <param name="keyword">The keyword to search for.</param>
6161
/// <returns><see langword="true" /> if the property contains the keyword; otherwise, <see langword="false" />.</returns>
62+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
6263
public static bool FullTextContains(this DbFunctions _, string property, string keyword)
6364
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FullTextContains)));
6465

@@ -69,6 +70,7 @@ public static bool FullTextContains(this DbFunctions _, string property, string
6970
/// <param name="property">The property to search.</param>
7071
/// <param name="keywords">The keywords to search for.</param>
7172
/// <returns><see langword="true" /> if the property contains all the keywords; otherwise, <see langword="false" />.</returns>
73+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
7274
public static bool FullTextContainsAll(this DbFunctions _, string property, params string[] keywords)
7375
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FullTextContainsAll)));
7476

@@ -79,6 +81,7 @@ public static bool FullTextContainsAll(this DbFunctions _, string property, para
7981
/// <param name="property">The property to search.</param>
8082
/// <param name="keywords">The keywords to search for.</param>
8183
/// <returns><see langword="true" /> if the property contains any of the keywords; otherwise, <see langword="false" />.</returns>
84+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
8285
public static bool FullTextContainsAny(this DbFunctions _, string property, params string[] keywords)
8386
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FullTextContainsAny)));
8487

@@ -89,6 +92,7 @@ public static bool FullTextContainsAny(this DbFunctions _, string property, para
8992
/// <param name="property">The property to score.</param>
9093
/// <param name="keywords">The keywords to score by.</param>
9194
/// <returns>The full-text search score.</returns>
95+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
9296
public static double FullTextScore(this DbFunctions _, string property, params string[] keywords)
9397
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FullTextScore)));
9498

@@ -98,6 +102,7 @@ public static double FullTextScore(this DbFunctions _, string property, params s
98102
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
99103
/// <param name="functions">The functions to compute the score for.</param>
100104
/// <returns>The combined score.</returns>
105+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
101106
public static double Rrf(this DbFunctions _, params double[] functions)
102107
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Rrf)));
103108

src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ protected override Expression VisitExtension(Expression expression)
7979
return base.VisitExtension(expression);
8080
}
8181

82-
// Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2))
82+
// Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2))
8383
case SqlFunctionExpression
8484
{
8585
Name: "FullTextContainsAny" or "FullTextContainsAll",
@@ -100,7 +100,7 @@ protected override Expression VisitExtension(Expression expression)
100100
fullTextContainsAllAnyFunction.TypeMapping);
101101
}
102102

103-
// Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2]))
103+
// Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2]))
104104
case SqlFunctionExpression
105105
{
106106
Name: "FullTextScore",
@@ -116,7 +116,7 @@ protected override Expression VisitExtension(Expression expression)
116116

117117
return new SqlFunctionExpression(
118118
fullTextScoreFunction.Name,
119-
scoringFunction: true,
119+
isScoringFunction: true,
120120
[property, sqlExpressionFactory.Constant(keywordValues, typeMapping)],
121121
fullTextScoreFunction.Type,
122122
fullTextScoreFunction.TypeMapping);

src/EFCore.Cosmos/Query/Internal/Expressions/SqlFunctionExpression.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public SqlFunctionExpression(
2626
IEnumerable<Expression> arguments,
2727
Type type,
2828
CoreTypeMapping? typeMapping)
29-
: this(name, scoringFunction: false, arguments, type, typeMapping)
29+
: this(name, isScoringFunction: false, arguments, type, typeMapping)
3030
{
3131
}
3232

@@ -36,17 +36,18 @@ public SqlFunctionExpression(
3636
/// any release. You should only use it directly in your code with extreme caution and knowing that
3737
/// doing so can result in application failures when updating to a new Entity Framework Core release.
3838
/// </summary>
39+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
3940
public SqlFunctionExpression(
4041
string name,
41-
bool scoringFunction,
42+
bool isScoringFunction,
4243
IEnumerable<Expression> arguments,
4344
Type type,
4445
CoreTypeMapping? typeMapping)
4546
: base(type, typeMapping)
4647
{
4748
Name = name;
48-
Arguments = arguments.ToList();
49-
IsScoringFunction = scoringFunction;
49+
Arguments = [.. arguments];
50+
IsScoringFunction = isScoringFunction;
5051
}
5152

5253
/// <summary>
@@ -63,6 +64,7 @@ public SqlFunctionExpression(
6364
/// any release. You should only use it directly in your code with extreme caution and knowing that
6465
/// doing so can result in application failures when updating to a new Entity Framework Core release.
6566
/// </summary>
67+
[Experimental(EFDiagnostics.CosmosFullTextSearchExperimental)]
6668
public virtual bool IsScoringFunction { get; }
6769

6870
/// <summary>

src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,42 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF
3636
nameof(CosmosDbFunctionsExtensions.FullTextContains)
3737
when arguments is [_, var property, var keyword] => sqlExpressionFactory.Function(
3838
"FullTextContains",
39-
[property, keyword],
39+
[
40+
property,
41+
keyword,
42+
],
4043
typeof(bool),
4144
typeMappingSource.FindMapping(typeof(bool))),
4245

4346
nameof(CosmosDbFunctionsExtensions.FullTextScore)
44-
when arguments is [_, var property, var keywords] => sqlExpressionFactory.ScoringFunction(
47+
when arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords]
48+
&& keywordClrType == typeof(string[]) => BuildScoringFunction(
49+
sqlExpressionFactory,
50+
"FullTextScore",
51+
[property, .. values.Select(x => sqlExpressionFactory.Constant(x))],
52+
typeof(double),
53+
typeMappingSource.FindMapping(typeof(double))),
54+
55+
nameof(CosmosDbFunctionsExtensions.FullTextScore)
56+
when arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords]
57+
&& keywordClrType == typeof(string[]) => BuildScoringFunction(
58+
sqlExpressionFactory,
59+
"FullTextScore",
60+
[property, keywords],
61+
typeof(double),
62+
typeMappingSource.FindMapping(typeof(double))),
63+
64+
nameof(CosmosDbFunctionsExtensions.FullTextScore)
65+
when arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => BuildScoringFunction(
66+
sqlExpressionFactory,
4567
"FullTextScore",
46-
[
47-
property,
48-
keywords,
49-
],
68+
[property, .. keywords.Items],
5069
typeof(double),
5170
typeMappingSource.FindMapping(typeof(double))),
5271

5372
nameof(CosmosDbFunctionsExtensions.Rrf)
54-
when arguments is [_, ArrayConstantExpression functions] => sqlExpressionFactory.ScoringFunction(
73+
when arguments is [_, ArrayConstantExpression functions] => BuildScoringFunction(
74+
sqlExpressionFactory,
5575
"RRF",
5676
functions.Items,
5777
typeof(double),
@@ -61,7 +81,7 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF
6181
when arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords]
6282
&& keywordClrType == typeof(string[]) => sqlExpressionFactory.Function(
6383
method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll",
64-
[property, ..values.Select(x => sqlExpressionFactory.Constant(x))],
84+
[property, .. values.Select(x => sqlExpressionFactory.Constant(x))],
6585
typeof(bool),
6686
typeMappingSource.FindMapping(typeof(bool))),
6787

@@ -83,4 +103,26 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF
83103
_ => null
84104
};
85105
}
106+
107+
private SqlExpression BuildScoringFunction(
108+
ISqlExpressionFactory sqlExpressionFactory,
109+
string functionName,
110+
IEnumerable<Expression> arguments,
111+
Type returnType,
112+
CoreTypeMapping? typeMapping = null)
113+
{
114+
var typeMappedArguments = new List<Expression>();
115+
116+
foreach (var argument in arguments)
117+
{
118+
typeMappedArguments.Add(argument is SqlExpression sqlArgument ? sqlExpressionFactory.ApplyDefaultTypeMapping(sqlArgument) : argument);
119+
}
120+
121+
return new SqlFunctionExpression(
122+
functionName,
123+
isScoringFunction: true,
124+
typeMappedArguments,
125+
returnType,
126+
typeMapping);
127+
}
86128
}

src/Shared/EFDiagnostics.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ internal static class EFDiagnostics
1919
public const string MetricsExperimental = "EF9101";
2020
public const string PagingExperimental = "EF9102";
2121
public const string CosmosVectorSearchExperimental = "EF9103";
22+
public const string CosmosFullTextSearchExperimental = "EF9104";
2223
}

test/EFCore.Cosmos.FunctionalTests/FullTextSearchCosmosTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
namespace Microsoft.EntityFrameworkCore;
99

10-
[CosmosCondition(CosmosCondition.DoesNotUseTokenCredential)]
10+
#pragma warning disable EF9104 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
11+
[CosmosCondition(CosmosCondition.DoesNotUseTokenCredential | CosmosCondition.IsNotEmulator)]
1112
public class FullTextSearchCosmosTest : IClassFixture<FullTextSearchCosmosTest.FullTextSearchFixture>
1213
{
1314
public FullTextSearchCosmosTest(FullTextSearchFixture fixture, ITestOutputHelper testOutputHelper)

test/EFCore.Cosmos.FunctionalTests/HybridSearchCosmosTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
namespace Microsoft.EntityFrameworkCore;
88

9+
#pragma warning disable EF9104 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
910
#pragma warning disable EF9103
10-
[CosmosCondition(CosmosCondition.DoesNotUseTokenCredential)]
11+
[CosmosCondition(CosmosCondition.DoesNotUseTokenCredential | CosmosCondition.IsNotEmulator)]
1112
public class HybridSearchCosmosTest : IClassFixture<HybridSearchCosmosTest.HybridSearchFixture>
1213
{
1314
public HybridSearchCosmosTest(HybridSearchFixture fixture, ITestOutputHelper testOutputHelper)

test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosCondition.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ public enum CosmosCondition
88
{
99
UsesTokenCredential = 1 << 0,
1010
DoesNotUseTokenCredential = 1 << 1,
11+
IsEmulator = 1 << 2,
12+
IsNotEmulator = 1 << 3,
1113
}

test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosConditionAttribute.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ public ValueTask<bool> IsMetAsync()
2424
isMet &= !TestEnvironment.UseTokenCredential;
2525
}
2626

27+
if (Conditions.HasFlag(CosmosCondition.IsEmulator))
28+
{
29+
isMet &= TestEnvironment.IsEmulator;
30+
}
31+
32+
if (Conditions.HasFlag(CosmosCondition.IsNotEmulator))
33+
{
34+
isMet &= !TestEnvironment.IsEmulator;
35+
}
36+
2737
return ValueTask.FromResult(isMet);
2838
}
2939

0 commit comments

Comments
 (0)