Skip to content

Commit ecba8a8

Browse files
committed
Cleanup around vector in Cosmos
- remove experimental from vector APIs, - renamed vector index model builder method from ForVector to IsVectorIndex, - renamed vector property model builder method from IsVector to IsVectorProperty, - use helper methods rather than extracting annotations directly in validation, - move some validation to container creation, so that queries are not blocked when Cosmos starts supporting new things (e.g. composite indexes) - split CosmosVectorType into two annotations (distance function and dimensions) so that we can keep CVT pubternal Fixes #35895 Fixes #35886 Fixes #35897 Fixes #35903 Fixes #35965
1 parent 62a94cb commit ecba8a8

21 files changed

+298
-196
lines changed

Diff for: src/EFCore.Cosmos/EFCore.Cosmos.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
<ImplicitUsings>true</ImplicitUsings>
1212
<NoWarn>$(NoWarn);EF9101</NoWarn> <!-- Metrics is experimental -->
1313
<NoWarn>$(NoWarn);EF9102</NoWarn> <!-- Paging is experimental -->
14-
<NoWarn>$(NoWarn);EF9103</NoWarn> <!-- Vector search is experimental -->
1514
</PropertyGroup>
1615

1716
<ItemGroup>

Diff for: src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs

+3-12
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,12 @@ public static double Rrf(this DbFunctions _, params double[] functions)
104104
/// <summary>
105105
/// Returns the distance between two vectors, using the distance function and data type defined using
106106
/// <see
107-
/// cref="CosmosPropertyBuilderExtensions.IsVector(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
107+
/// cref="CosmosPropertyBuilderExtensions.IsVectorProperty(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
108108
/// .
109109
/// </summary>
110110
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
111111
/// <param name="vector1">The first vector.</param>
112112
/// <param name="vector2">The second vector.</param>
113-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
114113
public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<byte> vector1, ReadOnlyMemory<byte> vector2)
115114
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(VectorDistance)));
116115

@@ -125,7 +124,6 @@ public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<byte> vec
125124
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
126125
/// property is leveraged.
127126
/// </param>
128-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
129127
public static double VectorDistance(
130128
this DbFunctions _,
131129
ReadOnlyMemory<byte> vector1,
@@ -145,7 +143,6 @@ public static double VectorDistance(
145143
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
146144
/// property is leveraged.
147145
/// </param>
148-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
149146
public static double VectorDistance(
150147
this DbFunctions _,
151148
ReadOnlyMemory<byte> vector1,
@@ -157,13 +154,12 @@ public static double VectorDistance(
157154
/// <summary>
158155
/// Returns the distance between two vectors, using the distance function and data type defined using
159156
/// <see
160-
/// cref="CosmosPropertyBuilderExtensions.IsVector(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
157+
/// cref="CosmosPropertyBuilderExtensions.IsVectorProperty(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
161158
/// .
162159
/// </summary>
163160
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
164161
/// <param name="vector1">The first vector.</param>
165162
/// <param name="vector2">The second vector.</param>
166-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
167163
public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<sbyte> vector1, ReadOnlyMemory<sbyte> vector2)
168164
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(VectorDistance)));
169165

@@ -178,7 +174,6 @@ public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<sbyte> ve
178174
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
179175
/// property is leveraged.
180176
/// </param>
181-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
182177
public static double VectorDistance(
183178
this DbFunctions _,
184179
ReadOnlyMemory<sbyte> vector1,
@@ -198,7 +193,6 @@ public static double VectorDistance(
198193
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
199194
/// property is leveraged.
200195
/// </param>
201-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
202196
public static double VectorDistance(
203197
this DbFunctions _,
204198
ReadOnlyMemory<sbyte> vector1,
@@ -210,13 +204,12 @@ public static double VectorDistance(
210204
/// <summary>
211205
/// Returns the distance between two vectors, using the distance function and data type defined using
212206
/// <see
213-
/// cref="CosmosPropertyBuilderExtensions.IsVector(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
207+
/// cref="CosmosPropertyBuilderExtensions.IsVectorProperty(Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder,Microsoft.Azure.Cosmos.DistanceFunction,int)" />
214208
/// .
215209
/// </summary>
216210
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
217211
/// <param name="vector1">The first vector.</param>
218212
/// <param name="vector2">The second vector.</param>
219-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
220213
public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<float> vector1, ReadOnlyMemory<float> vector2)
221214
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(VectorDistance)));
222215

@@ -231,7 +224,6 @@ public static double VectorDistance(this DbFunctions _, ReadOnlyMemory<float> ve
231224
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
232225
/// property is leveraged.
233226
/// </param>
234-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
235227
public static double VectorDistance(
236228
this DbFunctions _,
237229
ReadOnlyMemory<float> vector1,
@@ -251,7 +243,6 @@ public static double VectorDistance(
251243
/// expression. If <see langword="true" />, then brute force is used, otherwise any index defined on the vector
252244
/// property is leveraged.
253245
/// </param>
254-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
255246
public static double VectorDistance(
256247
this DbFunctions _,
257248
ReadOnlyMemory<float> vector1,

Diff for: src/EFCore.Cosmos/Extensions/CosmosIndexBuilderExtensions.cs

+4-8
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ public static class CosmosIndexBuilderExtensions
2727
/// <param name="indexBuilder">The builder for the index being configured.</param>
2828
/// <param name="indexType">The type of vector index to create.</param>
2929
/// <returns>A builder to further configure the index.</returns>
30-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
31-
public static IndexBuilder ForVectors(this IndexBuilder indexBuilder, VectorIndexType? indexType)
30+
public static IndexBuilder IsVectorIndex(this IndexBuilder indexBuilder, VectorIndexType? indexType)
3231
{
3332
indexBuilder.Metadata.SetVectorIndexType(indexType);
3433

@@ -46,11 +45,10 @@ public static IndexBuilder ForVectors(this IndexBuilder indexBuilder, VectorInde
4645
/// <param name="indexBuilder">The builder for the index being configured.</param>
4746
/// <param name="indexType">The type of vector index to create.</param>
4847
/// <returns>A builder to further configure the index.</returns>
49-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
50-
public static IndexBuilder<TEntity> ForVectors<TEntity>(
48+
public static IndexBuilder<TEntity> IsVectorIndex<TEntity>(
5149
this IndexBuilder<TEntity> indexBuilder,
5250
VectorIndexType? indexType)
53-
=> (IndexBuilder<TEntity>)ForVectors((IndexBuilder)indexBuilder, indexType);
51+
=> (IndexBuilder<TEntity>)IsVectorIndex((IndexBuilder)indexBuilder, indexType);
5452

5553
/// <summary>
5654
/// Configures whether the index as a vector index with the given vector index type, such as "flat", "diskANN", or "quantizedFlat".
@@ -67,8 +65,7 @@ public static IndexBuilder<TEntity> ForVectors<TEntity>(
6765
/// The same builder instance if the configuration was applied,
6866
/// <see langword="null" /> otherwise.
6967
/// </returns>
70-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
71-
public static IConventionIndexBuilder? ForVectors(
68+
public static IConventionIndexBuilder? IsVectorIndex(
7269
this IConventionIndexBuilder indexBuilder,
7370
VectorIndexType? indexType,
7471
bool fromDataAnnotation = false)
@@ -93,7 +90,6 @@ public static IndexBuilder<TEntity> ForVectors<TEntity>(
9390
/// <param name="indexType">The index type to use.</param>
9491
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
9592
/// <returns><see langword="true" /> if the index can be configured for vectors.</returns>
96-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
9793
public static bool CanSetVectorIndexType(
9894
this IConventionIndexBuilder indexBuilder,
9995
VectorIndexType? indexType,

Diff for: src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs

-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public static class CosmosIndexExtensions
2222
/// </summary>
2323
/// <param name="index">The index.</param>
2424
/// <returns>The index type to use, or <see langword="null" /> if none is set.</returns>
25-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
2625
public static VectorIndexType? GetVectorIndexType(this IReadOnlyIndex index)
2726
=> (index is RuntimeIndex)
2827
? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
@@ -34,7 +33,6 @@ public static class CosmosIndexExtensions
3433
/// </summary>
3534
/// <param name="index">The index.</param>
3635
/// <param name="indexType">The index type to use.</param>
37-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
3836
public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType? indexType)
3937
=> index.SetAnnotation(CosmosAnnotationNames.VectorIndexType, indexType);
4038

@@ -46,7 +44,6 @@ public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType?
4644
/// <param name="index">The index.</param>
4745
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
4846
/// <returns>The configured value.</returns>
49-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
5047
public static string? SetVectorIndexType(
5148
this IConventionIndex index,
5249
VectorIndexType? indexType,
@@ -61,7 +58,6 @@ public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType?
6158
/// </summary>
6259
/// <param name="property">The property.</param>
6360
/// <returns>The <see cref="ConfigurationSource" /> for whether the index is clustered.</returns>
64-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
6561
public static ConfigurationSource? GetVectorIndexTypeConfigurationSource(this IConventionIndex property)
6662
=> property.FindAnnotation(CosmosAnnotationNames.VectorIndexType)?.GetConfigurationSource();
6763

Diff for: src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs

+28-23
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,14 @@ public static bool CanSetJsonProperty(
116116
/// <param name="distanceFunction">The distance function for a vector comparisons.</param>
117117
/// <param name="dimensions">The number of dimensions in the vector.</param>
118118
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
119-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
120-
public static PropertyBuilder IsVector(
119+
public static PropertyBuilder IsVectorProperty(
121120
this PropertyBuilder propertyBuilder,
122121
DistanceFunction distanceFunction,
123122
int dimensions)
124123
{
125-
propertyBuilder.Metadata.SetVectorType(CreateVectorType(distanceFunction, dimensions));
124+
propertyBuilder.Metadata.SetVectorDistanceFunction(ValidateVectorDistanceFunction(distanceFunction));
125+
propertyBuilder.Metadata.SetVectorDimensions(dimensions);
126+
126127
return propertyBuilder;
127128
}
128129

@@ -142,12 +143,11 @@ public static PropertyBuilder IsVector(
142143
/// <param name="distanceFunction">The distance function for a vector comparisons.</param>
143144
/// <param name="dimensions">The number of dimensions in the vector.</param>
144145
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
145-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
146-
public static PropertyBuilder<TProperty> IsVector<TProperty>(
146+
public static PropertyBuilder<TProperty> IsVectorProperty<TProperty>(
147147
this PropertyBuilder<TProperty> propertyBuilder,
148148
DistanceFunction distanceFunction,
149149
int dimensions)
150-
=> (PropertyBuilder<TProperty>)IsVector((PropertyBuilder)propertyBuilder, distanceFunction, dimensions);
150+
=> (PropertyBuilder<TProperty>)IsVectorProperty((PropertyBuilder)propertyBuilder, distanceFunction, dimensions);
151151

152152
/// <summary>
153153
/// Configures the property as a vector for Azure Cosmos DB.
@@ -164,25 +164,25 @@ public static PropertyBuilder<TProperty> IsVector<TProperty>(
164164
/// The same builder instance if the configuration was applied,
165165
/// <see langword="null" /> otherwise.
166166
/// </returns>
167-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
168-
public static IConventionPropertyBuilder? IsVector(
167+
public static IConventionPropertyBuilder? IsVectorProperty(
169168
this IConventionPropertyBuilder propertyBuilder,
170169
DistanceFunction distanceFunction,
171170
int dimensions,
172171
bool fromDataAnnotation = false)
173172
{
174-
if (!propertyBuilder.CanSetIsVector(distanceFunction, dimensions, fromDataAnnotation))
173+
if (!propertyBuilder.CanSetIsVectorProperty(distanceFunction, dimensions, fromDataAnnotation))
175174
{
176175
return null;
177176
}
178177

179-
propertyBuilder.Metadata.SetVectorType(CreateVectorType(distanceFunction, dimensions), fromDataAnnotation);
178+
propertyBuilder.Metadata.SetVectorDistanceFunction(ValidateVectorDistanceFunction(distanceFunction), fromDataAnnotation);
179+
propertyBuilder.Metadata.SetVectorDimensions(dimensions, fromDataAnnotation);
180180

181181
return propertyBuilder;
182182
}
183183

184184
/// <summary>
185-
/// Returns a value indicating whether the vector type can be set.
185+
/// Returns a value indicating whether the vector distance function and dimensions can be set.
186186
/// </summary>
187187
/// <remarks>
188188
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
@@ -192,18 +192,30 @@ public static PropertyBuilder<TProperty> IsVector<TProperty>(
192192
/// <param name="distanceFunction">The distance function for a vector comparisons.</param>
193193
/// <param name="dimensions">The number of dimensions in the vector.</param>
194194
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
195-
/// <returns><see langword="true" /> if the vector type can be set.</returns>
196-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
197-
public static bool CanSetIsVector(
195+
/// <returns><see langword="true" /> if the vector distance function and dimensions can be set.</returns>
196+
public static bool CanSetIsVectorProperty(
198197
this IConventionPropertyBuilder propertyBuilder,
199198
DistanceFunction distanceFunction,
200199
int dimensions,
201200
bool fromDataAnnotation = false)
202201
=> propertyBuilder.CanSetAnnotation(
203-
CosmosAnnotationNames.VectorType,
204-
CreateVectorType(distanceFunction, dimensions),
202+
CosmosAnnotationNames.VectorDistanceFunction,
203+
ValidateVectorDistanceFunction(distanceFunction),
204+
fromDataAnnotation)
205+
&& propertyBuilder.CanSetAnnotation(
206+
CosmosAnnotationNames.VectorDimensions,
207+
dimensions,
205208
fromDataAnnotation);
206209

210+
private static DistanceFunction ValidateVectorDistanceFunction(DistanceFunction distanceFunction)
211+
=> Enum.IsDefined(distanceFunction)
212+
? distanceFunction
213+
: throw new ArgumentException(
214+
CoreStrings.InvalidEnumValue(
215+
distanceFunction,
216+
nameof(distanceFunction),
217+
typeof(DistanceFunction)));
218+
207219
/// <summary>
208220
/// Configures this property to be the etag concurrency token.
209221
/// </summary>
@@ -237,13 +249,6 @@ public static PropertyBuilder<TProperty> IsETagConcurrency<TProperty>(
237249
this PropertyBuilder<TProperty> propertyBuilder)
238250
=> (PropertyBuilder<TProperty>)IsETagConcurrency((PropertyBuilder)propertyBuilder);
239251

240-
[Experimental(EFDiagnostics.CosmosVectorSearchExperimental)]
241-
private static CosmosVectorType CreateVectorType(DistanceFunction distanceFunction, int dimensions)
242-
=> Enum.IsDefined(distanceFunction)
243-
? new CosmosVectorType(distanceFunction, dimensions)
244-
: throw new ArgumentException(
245-
CoreStrings.InvalidEnumValue(distanceFunction, nameof(distanceFunction), typeof(DistanceFunction)));
246-
247252
/// <summary>
248253
/// Enables full-text search for this property using a specified language.
249254
/// </summary>

0 commit comments

Comments
 (0)