diff --git a/src/DataStax.AstraDB.DataApi/Core/Commands/Command.cs b/src/DataStax.AstraDB.DataApi/Core/Commands/Command.cs index 60eba05..cd538b2 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Commands/Command.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Commands/Command.cs @@ -326,7 +326,7 @@ private async Task RunCommandAsync(HttpMethod method, bool runSynchronousl responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); MaybeLogDebugMessage("Response Status Code: {StatusCode}", response.StatusCode); MaybeLogDebugMessage("Content: {Content}", responseContent); - throw new HttpRequestException($"Request to failed with status code {response.StatusCode}."); + throw new HttpRequestException($"Request failed with status code {response.StatusCode}."); } } responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); diff --git a/src/DataStax.AstraDB.DataApi/Core/Database.cs b/src/DataStax.AstraDB.DataApi/Core/Database.cs index a90a132..1ed0161 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Database.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Database.cs @@ -905,7 +905,7 @@ private async Task> ListTablesAsync(DatabaseCommandOption /// Synchronous version of /// /// - public IEnumerable ListTableNames() + public List ListTableNames() { return ListTableNames(null); } @@ -915,7 +915,7 @@ public IEnumerable ListTableNames() /// /// The options to use for the command, useful for overriding the keyspace, for example. /// - public IEnumerable ListTableNames(DatabaseCommandOptions options) + public List ListTableNames(DatabaseCommandOptions options) { return ListTableNamesAsync(options, true, true).ResultSync(); } @@ -924,7 +924,7 @@ public IEnumerable ListTableNames(DatabaseCommandOptions options) /// List the tables in the database. /// /// - public Task> ListTableNamesAsync() + public Task> ListTableNamesAsync() { return ListTableNamesAsync(null); } @@ -934,12 +934,12 @@ public Task> ListTableNamesAsync() /// /// The options to use for the command, useful for overriding the keyspace, for example. /// - public Task> ListTableNamesAsync(DatabaseCommandOptions options) + public Task> ListTableNamesAsync(DatabaseCommandOptions options) { return ListTableNamesAsync(options, true, false); } - private async Task> ListTableNamesAsync(DatabaseCommandOptions options, bool includeDetails, bool runSynchronously) + private async Task> ListTableNamesAsync(DatabaseCommandOptions options, bool includeDetails, bool runSynchronously) { var payload = new { diff --git a/src/DataStax.AstraDB.DataApi/Core/Query/DocumentFindOptions.cs b/src/DataStax.AstraDB.DataApi/Core/Query/DocumentFindOptions.cs index b19652a..6cb4a54 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Query/DocumentFindOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Query/DocumentFindOptions.cs @@ -20,6 +20,10 @@ namespace DataStax.AstraDB.DataApi.Core.Query; public class DocumentFindOptions : FindOptions> { + /// + /// The sort to apply when running the query. + /// [JsonIgnore] public override DocumentSortBuilder Sort { get; set; } + } diff --git a/src/DataStax.AstraDB.DataApi/Core/Query/FindOptions.cs b/src/DataStax.AstraDB.DataApi/Core/Query/FindOptions.cs index 172785b..fcb6e9a 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Query/FindOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Query/FindOptions.cs @@ -25,7 +25,11 @@ public abstract class FindOptions : IFindOptions where TSort [JsonIgnore] public IProjectionBuilder Projection { get; set; } - internal bool? IncludeSimilarity { get; set; } + /// + /// Whether to include a similarity score in the results or not (when performing a vector sort). + /// + [JsonIgnore] + public bool? IncludeSimilarity { get; set; } protected bool? _includeSortVector; diff --git a/src/DataStax.AstraDB.DataApi/Core/Results/ListTableNamesResult.cs b/src/DataStax.AstraDB.DataApi/Core/Results/ListTableNamesResult.cs index fef3f3e..240d1d4 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Results/ListTableNamesResult.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Results/ListTableNamesResult.cs @@ -14,6 +14,7 @@ * limitations under the License. */ +using System.Collections.Generic; using System.Text.Json.Serialization; namespace DataStax.AstraDB.DataApi.Core.Results; @@ -24,8 +25,8 @@ namespace DataStax.AstraDB.DataApi.Core.Results; public class ListTableNamesResult { /// - /// An array of table names. + /// The list of table names. /// [JsonPropertyName("tables")] - public string[] Tables { get; set; } + public List Tables { get; set; } } \ No newline at end of file diff --git a/src/DataStax.AstraDB.DataApi/Core/TableDeleteOptions.cs b/src/DataStax.AstraDB.DataApi/Core/TableDeleteOptions.cs new file mode 100644 index 0000000..b083e62 --- /dev/null +++ b/src/DataStax.AstraDB.DataApi/Core/TableDeleteOptions.cs @@ -0,0 +1,35 @@ +/* + * Copyright DataStax, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using DataStax.AstraDB.DataApi.Core.Query; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; + +namespace DataStax.AstraDB.DataApi.Core; + +/// +/// Options for deleting a row from a table +/// +/// +public class TableDeleteOptions where T : class +{ + internal Filter Filter { get; set; } + + [JsonInclude] + [JsonPropertyName("filter")] + internal Dictionary FilterMap => Filter == null ? new Dictionary() : Filter.Serialize(); +} diff --git a/src/DataStax.AstraDB.DataApi/DataStax.AstraDB.DataApi.csproj b/src/DataStax.AstraDB.DataApi/DataStax.AstraDB.DataApi.csproj index 5de6c43..0869731 100644 --- a/src/DataStax.AstraDB.DataApi/DataStax.AstraDB.DataApi.csproj +++ b/src/DataStax.AstraDB.DataApi/DataStax.AstraDB.DataApi.csproj @@ -18,6 +18,7 @@ Apache-2.0 packageIcon.png README.md + true diff --git a/src/DataStax.AstraDB.DataApi/SerDes/TableInsertManyResultConverter.cs b/src/DataStax.AstraDB.DataApi/SerDes/TableInsertManyResultConverter.cs index eca452b..5f739a1 100644 --- a/src/DataStax.AstraDB.DataApi/SerDes/TableInsertManyResultConverter.cs +++ b/src/DataStax.AstraDB.DataApi/SerDes/TableInsertManyResultConverter.cs @@ -14,24 +14,33 @@ * limitations under the License. */ +using DataStax.AstraDB.DataApi.Core.Results; +using DataStax.AstraDB.DataApi.Tables; using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; -using DataStax.AstraDB.DataApi.Core.Results; -using DataStax.AstraDB.DataApi.Tables; namespace DataStax.AstraDB.DataApi.SerDes; -public class TableInsertManyResultConverter : JsonConverter +internal class TableInsertOneResultConverter : TableInsertResultConverter { - public override TableInsertManyResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +} + +internal class TableInsertManyResultConverter : TableInsertResultConverter +{ +} + +internal class TableInsertResultConverter : JsonConverter where T : TableInsertManyResult, new() +{ + + public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("Expected StartObject token"); - var result = new TableInsertManyResult(); + var result = new T(); JsonDocument insertedIdsDoc = null; JsonDocument documentResponsesDoc = null; @@ -207,7 +216,7 @@ private object DeserializeValue(JsonElement element, PrimaryKeySchema schema, Js } } - public override void Write(Utf8JsonWriter writer, TableInsertManyResult value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { throw new NotSupportedException("Serialization is not implemented for TableInsertManyResult"); } diff --git a/src/DataStax.AstraDB.DataApi/Tables/Column.cs b/src/DataStax.AstraDB.DataApi/Tables/Column.cs index d5b5519..ca1829d 100644 --- a/src/DataStax.AstraDB.DataApi/Tables/Column.cs +++ b/src/DataStax.AstraDB.DataApi/Tables/Column.cs @@ -21,93 +21,183 @@ namespace DataStax.AstraDB.DataApi.Tables; +/// +/// Represents a column in a table +/// [JsonConverter(typeof(ColumnConverter))] public abstract class Column { + /// + /// The type of the column + /// [JsonIgnore] public abstract string Type { get; } } +/// +/// A column that holds text values +/// public class TextColumn : Column { + /// + /// Defines the column as type text + /// [JsonPropertyName("type")] public override string Type => "text"; } +/// +/// A column that holds UUID values +/// public class GuidColumn : Column { + /// + /// Defines the column as type uuid + /// [JsonPropertyName("type")] public override string Type => "uuid"; } +/// +/// A column that holds integer values +/// public class IntColumn : Column { + /// + /// Defines the column as type int + /// [JsonPropertyName("type")] public override string Type => "int"; } +/// +/// A column that holds long integer values +/// public class LongColumn : Column { + /// + /// Defines the column as type bigint + /// [JsonPropertyName("type")] public override string Type => "bigint"; } +/// +/// A column that holds decimal values +/// public class DecimalColumn : Column { + /// + /// Defines the column as type decimal + /// [JsonPropertyName("type")] public override string Type => "decimal"; } +/// +/// A column that holds float values +/// public class FloatColumn : Column { + /// + /// Defines the column as type float + /// [JsonPropertyName("type")] public override string Type => "float"; } +/// +/// A column that holds double values +/// public class DoubleColumn : Column { + /// + /// Defines the column as type double + /// [JsonPropertyName("type")] public override string Type => "double"; } +/// +/// A column that holds boolean values +/// public class BooleanColumn : Column { + /// + /// Defines the column as type boolean + /// [JsonPropertyName("type")] public override string Type => "boolean"; } +/// +/// A column that holds date/time values +/// public class DateTimeColumn : Column { + /// + /// Defines the column as type timestamp + /// [JsonPropertyName("type")] public override string Type => "timestamp"; } +/// +/// A column that holds binary values +/// public class BlobColumn : Column { + /// + /// Defines the column as type blob + /// [JsonPropertyName("type")] public override string Type => "blob"; } +/// +/// A column that holds IP address values +/// public class IPAddressColumn : Column { + /// + /// Defines the column as type inet + /// [JsonPropertyName("type")] public override string Type => "inet"; } +/// +/// A column that holds duration values +/// public class DurationColumn : Column { + /// + /// Defines the column as type duration + /// [JsonPropertyName("type")] public override string Type => "duration"; } +/// +/// A column that holds dictionary/map values +/// public class DictionaryColumn : Column { + /// + /// Defines the column as type map + /// [JsonPropertyName("type")] public override string Type => "map"; + /// + /// The type of the keys in the dictionary + /// [JsonPropertyName("keyType")] public string KeyType { get; set; } + /// + /// The type of the values in the dictionary + /// [JsonPropertyName("valueType")] public string ValueType { get; set; } @@ -117,14 +207,26 @@ internal DictionaryColumn(string keyType, string valueType) ValueType = valueType; } + /// + /// Creates a new instance of the class. + /// public DictionaryColumn() { } } +/// +/// A column that holds list/array values +/// public class ListColumn : Column { + /// + /// Defines the column as type list + /// [JsonPropertyName("type")] public override string Type => "list"; + /// + /// The type of the values in the list + /// [JsonPropertyName("valueType")] public string ValueType { get; set; } @@ -133,14 +235,26 @@ internal ListColumn(string valueType) ValueType = valueType; } + /// + /// Creates a new instance of the class. + /// public ListColumn() { } } +/// +/// A column that holds set values +/// public class SetColumn : Column { + /// + /// Defines the column as type set + /// [JsonPropertyName("type")] public override string Type => "set"; + /// + /// The type of the values in the set + /// [JsonPropertyName("valueType")] public string ValueType { get; set; } @@ -149,14 +263,26 @@ internal SetColumn(string valueType) ValueType = valueType; } + /// + /// Creates a new instance of the class. + /// public SetColumn() { } } +/// +/// A column that holds vector values +/// public class VectorColumn : Column { + /// + /// Defines the column as type vector + /// [JsonPropertyName("type")] public override string Type => "vector"; + /// + /// The dimension of the vector + /// [JsonPropertyName("dimension")] public int Dimension { get; set; } @@ -165,18 +291,44 @@ internal VectorColumn(int dimension) Dimension = dimension; } + /// + /// Creates a new instance of the class. + /// public VectorColumn() { } } +/// +/// A column that holds vector values that are generated by a vectorization service +/// public class VectorizeColumn : VectorColumn { + /// + /// The vectorization service options + /// [JsonPropertyName("service")] public VectorServiceOptions ServiceOptions { get; set; } + /// + /// Creates a new instance of the class with the specified dimension and service options. + /// + /// + /// public VectorizeColumn(int dimension, VectorServiceOptions serviceOptions) : base(dimension) { ServiceOptions = serviceOptions; } + /// + /// Creates a new instance of the class with the specified service options. + /// + /// + public VectorizeColumn(VectorServiceOptions serviceOptions) + { + ServiceOptions = serviceOptions; + } + + /// + /// Creates a new instance of the class. + /// public VectorizeColumn() { } } \ No newline at end of file diff --git a/src/DataStax.AstraDB.DataApi/Tables/Table.cs b/src/DataStax.AstraDB.DataApi/Tables/Table.cs index c82a665..df4cca0 100644 --- a/src/DataStax.AstraDB.DataApi/Tables/Table.cs +++ b/src/DataStax.AstraDB.DataApi/Tables/Table.cs @@ -386,7 +386,7 @@ private async Task RunInsertManyAsync(IEnumerable rows /// Synchronous version of /// /// - public TableInsertManyResult InsertOne(T row) + public TableInsertOneResult InsertOne(T row) { return InsertOne(row, null); } @@ -395,7 +395,7 @@ public TableInsertManyResult InsertOne(T row) /// Synchronous version of /// /// - public TableInsertManyResult InsertOne(T row, CommandOptions commandOptions) + public TableInsertOneResult InsertOne(T row, CommandOptions commandOptions) { return InsertOneAsync(row, commandOptions, true).ResultSync(); } @@ -405,19 +405,19 @@ public TableInsertManyResult InsertOne(T row, CommandOptions commandOptions) /// /// /// - public Task InsertOneAsync(T row) + public Task InsertOneAsync(T row) { return InsertOneAsync(row, null); } /// /// - public Task InsertOneAsync(T row, CommandOptions commandOptions) + public Task InsertOneAsync(T row, CommandOptions commandOptions) { return InsertOneAsync(row, commandOptions, false); } - private async Task InsertOneAsync(T row, CommandOptions commandOptions, bool runSynchronously) + private async Task InsertOneAsync(T row, CommandOptions commandOptions, bool runSynchronously) { var payload = new { @@ -425,7 +425,7 @@ private async Task InsertOneAsync(T row, CommandOptions c }; commandOptions = SetRowSerializationOptions(commandOptions, true); var command = CreateCommand("insertOne").WithPayload(payload).AddCommandOptions(commandOptions); - var response = await command.RunAsyncReturnStatus(runSynchronously).ConfigureAwait(false); + var response = await command.RunAsyncReturnStatus(runSynchronously).ConfigureAwait(false); return response.Result; } @@ -522,51 +522,168 @@ internal async Task, FindStatusResult return response; } + /// + /// Synchronous version of + public T FindOne() + { + return FindOne(null, null, null); + } + + /// + /// Synchronous version of + public T FindOne(Filter filter) + { + return FindOne(filter, null, null); + } + + /// + /// Synchronous version of + public T FindOne(Filter filter, CommandOptions commandOptions) + { + return FindOne(filter, null, commandOptions); + } + + /// + /// Synchronous version of + public T FindOne(TableFindOptions findOptions) + { + return FindOne(null, findOptions, null); + } + + /// + /// Synchronous version of + public T FindOne(Filter filter, TableFindOptions findOptions) + { + return FindOne(filter, findOptions, null); + } + + /// + /// Synchronous version of + public T FindOne(Filter filter, TableFindOptions findOptions, CommandOptions commandOptions) + { + return FindOne(filter, findOptions, commandOptions); + } + + /// + /// Synchronous version of + public TResult FindOne() where TResult : class + { + return FindOne(null, null, null); + } + + /// + /// Synchronous version of + public TResult FindOne(Filter filter) where TResult : class + { + return FindOne(filter, null, null); + } + + /// + /// Synchronous version of + public TResult FindOne(Filter filter, CommandOptions commandOptions) where TResult : class + { + return FindOne(filter, null, commandOptions); + } + + /// + /// Synchronous version of + public TResult FindOne(Filter filter, TableFindOptions findOptions) where TResult : class + { + return FindOne(filter, findOptions, null); + } + + /// + /// Synchronous version of + public TResult FindOne(Filter filter, TableFindOptions findOptions, CommandOptions commandOptions) where TResult : class + { + return FindOneAsync(filter, findOptions, commandOptions, true).ResultSync(); + } + + /// + /// Find a single row in the table. + /// + /// public Task FindOneAsync() { return FindOneAsync(null, null, null); } + /// + /// Find a single row in the table that matches the specified filter. + /// + /// + /// public Task FindOneAsync(Filter filter) { return FindOneAsync(filter, null, null); } + /// + /// public Task FindOneAsync(Filter filter, CommandOptions commandOptions) { return FindOneAsync(filter, null, commandOptions); } + /// + /// Find a single row in the table using the specified find options. + /// + /// Specify Sort options for the find operation. + /// + public Task FindOneAsync(TableFindOptions findOptions) + { + return FindOneAsync(null, findOptions, null); + } + + /// + /// Specify Sort options for the find operation. public Task FindOneAsync(Filter filter, TableFindOptions findOptions) { return FindOneAsync(filter, findOptions, null); } + /// + /// public Task FindOneAsync(Filter filter, TableFindOptions findOptions, CommandOptions commandOptions) { return FindOneAsync(filter, findOptions, commandOptions); } + /// + /// Find a single row in the table, specifying a different result row class type + /// (useful when you want to project only certain fields). + /// + /// + /// public Task FindOneAsync() where TResult : class { return FindOneAsync(null, null, null); } + /// + /// + /// public Task FindOneAsync(Filter filter) where TResult : class { return FindOneAsync(filter, null, null); } + /// + /// public Task FindOneAsync(Filter filter, CommandOptions commandOptions) where TResult : class { return FindOneAsync(filter, null, commandOptions); } + /// + /// Specify Sort options for the find operation. public Task FindOneAsync(Filter filter, TableFindOptions findOptions) where TResult : class { return FindOneAsync(filter, findOptions, null); } + /// + /// public Task FindOneAsync(Filter filter, TableFindOptions findOptions, CommandOptions commandOptions) where TResult : class { return FindOneAsync(filter, findOptions, commandOptions, false); @@ -621,112 +738,59 @@ private CommandOptions SetRowSerializationOptions(CommandOptions comman return commandOptions; } - /// - /// Synchronous version of - /// - /// - public UpdateResult UpdateOne(UpdateBuilder update, UpdateOneOptions updateOptions) - { - return UpdateOne(null, update, updateOptions, null); - } - - /// - /// Synchronous version of - /// - /// - public UpdateResult UpdateOne(UpdateBuilder update, UpdateOneOptions updateOptions, CommandOptions commandOptions) - { - return UpdateOne(null, update, updateOptions, commandOptions); - } - /// /// Synchronous version of /// /// - public UpdateResult UpdateOne(Filter filter, UpdateBuilder update) - { - return UpdateOne(filter, update, new UpdateOneOptions(), null); - } - - /// - /// Synchronous version of - /// - /// - public UpdateResult UpdateOne(Filter filter, UpdateBuilder update, UpdateOneOptions updateOptions) + public void UpdateOne(Filter filter, UpdateBuilder update) { - return UpdateOne(filter, update, updateOptions, null); + UpdateOne(filter, update, null); } /// - /// Synchronous version of + /// Synchronous version of /// - /// - public UpdateResult UpdateOne(Filter filter, UpdateBuilder update, UpdateOneOptions updateOptions, CommandOptions commandOptions) + /// + public void UpdateOne(Filter filter, UpdateBuilder update, CommandOptions commandOptions) { - var response = UpdateOneAsync(filter, update, updateOptions, commandOptions, true).ResultSync(); - return response; - } - - /// - /// Update a single row in the table using the provided update builder and options. - /// - /// - /// - /// - public Task UpdateOneAsync(UpdateBuilder update, UpdateOneOptions updateOptions) - { - return UpdateOneAsync(null, update, updateOptions, null); - } - - /// - /// - public Task UpdateOneAsync(UpdateBuilder update, UpdateOneOptions updateOptions, CommandOptions commandOptions) - { - return UpdateOneAsync(null, update, updateOptions, commandOptions); + UpdateOneAsync(filter, update, commandOptions, true).ResultSync(); } /// /// Update a single row in the table using the provided filter and update builder. /// - /// This is similar to but does not return the updated document. /// /// /// /// - public Task UpdateOneAsync(Filter filter, UpdateBuilder update) + public Task UpdateOneAsync(Filter filter, UpdateBuilder update) { - return UpdateOneAsync(filter, update, null, null); + return UpdateOneAsync(filter, update, null); } /// - /// - public Task UpdateOneAsync(Filter filter, UpdateBuilder update, UpdateOneOptions updateOptions) - { - return UpdateOneAsync(filter, update, updateOptions, null); - } - - /// /// - public Task UpdateOneAsync(Filter filter, UpdateBuilder update, UpdateOneOptions updateOptions, CommandOptions commandOptions) + public Task UpdateOneAsync(Filter filter, UpdateBuilder update, CommandOptions commandOptions) { - return UpdateOneAsync(filter, update, updateOptions, commandOptions, false); + return UpdateOneAsync(filter, update, commandOptions, false); } - internal async Task UpdateOneAsync(Filter filter, UpdateBuilder update, UpdateOneOptions updateOptions, CommandOptions commandOptions, bool runSynchronously) + internal async Task UpdateOneAsync(Filter filter, UpdateBuilder update, CommandOptions commandOptions, bool runSynchronously) { - updateOptions = updateOptions ?? new UpdateOneOptions(); - updateOptions.Filter = filter; - updateOptions.Update = update; + var updateOptions = new UpdateOneOptions + { + Filter = filter, + Update = update + }; var command = CreateCommand("updateOne").WithPayload(updateOptions).AddCommandOptions(commandOptions); - var response = await command.RunAsyncReturnStatus(runSynchronously).ConfigureAwait(false); - return response.Result; + await command.RunAsyncReturnStatus(runSynchronously).ConfigureAwait(false); } /// /// This is a synchronous version of /// - /// - public DeleteResult DeleteOne(DeleteOptions deleteOptions) + /// + public DeleteResult DeleteOne(TableDeleteOptions deleteOptions) { return DeleteOne(null, deleteOptions, null); } @@ -737,7 +801,7 @@ public DeleteResult DeleteOne(DeleteOptions deleteOptions) /// public DeleteResult DeleteOne(Filter filter) { - return DeleteOne(filter, new DeleteOptions(), null); + return DeleteOne(filter, null, null); } /// @@ -746,32 +810,32 @@ public DeleteResult DeleteOne(Filter filter) /// public DeleteResult DeleteOne(Filter filter, CommandOptions commandOptions) { - return DeleteOne(filter, new DeleteOptions(), commandOptions); + return DeleteOne(filter, null, commandOptions); } /// - /// This is a synchronous version of + /// This is a synchronous version of /// - /// - public DeleteResult DeleteOne(DeleteOptions deleteOptions, CommandOptions commandOptions) + /// + public DeleteResult DeleteOne(TableDeleteOptions deleteOptions, CommandOptions commandOptions) { return DeleteOne(null, deleteOptions, commandOptions); } /// - /// This is a synchronous version of + /// This is a synchronous version of /// - /// - public DeleteResult DeleteOne(Filter filter, DeleteOptions deleteOptions) + /// + public DeleteResult DeleteOne(Filter filter, TableDeleteOptions deleteOptions) { return DeleteOne(filter, deleteOptions, null); } /// - /// This is a synchronous version of + /// This is a synchronous version of /// - /// - public DeleteResult DeleteOne(Filter filter, DeleteOptions deleteOptions, CommandOptions commandOptions) + /// + public DeleteResult DeleteOne(Filter filter, TableDeleteOptions deleteOptions, CommandOptions commandOptions) { var response = DeleteOneAsync(filter, deleteOptions, commandOptions, true).ResultSync(); return response; @@ -782,7 +846,7 @@ public DeleteResult DeleteOne(Filter filter, DeleteOptions deleteOptions, /// /// /// - public Task DeleteOneAsync(DeleteOptions deleteOptions) + public Task DeleteOneAsync(TableDeleteOptions deleteOptions) { return DeleteOneAsync(null, deleteOptions, null); } @@ -794,63 +858,78 @@ public Task DeleteOneAsync(DeleteOptions deleteOptions) /// public Task DeleteOneAsync(Filter filter) { - return DeleteOneAsync(filter, new DeleteOptions(), null); + return DeleteOneAsync(filter, null, null); } /// /// public Task DeleteOneAsync(Filter filter, CommandOptions commandOptions) { - return DeleteOneAsync(filter, new DeleteOptions(), commandOptions); + return DeleteOneAsync(filter, null, commandOptions); } - /// + /// /// - public Task DeleteOneAsync(DeleteOptions deleteOptions, CommandOptions commandOptions) + public Task DeleteOneAsync(TableDeleteOptions deleteOptions, CommandOptions commandOptions) { return DeleteOneAsync(null, deleteOptions, commandOptions); } /// /// - public Task DeleteOneAsync(Filter filter, DeleteOptions deleteOptions) + public Task DeleteOneAsync(Filter filter, TableDeleteOptions deleteOptions) { return DeleteOneAsync(filter, deleteOptions, null); } - /// + /// /// - public Task DeleteOneAsync(Filter filter, DeleteOptions deleteOptions, CommandOptions commandOptions) + public Task DeleteOneAsync(Filter filter, TableDeleteOptions deleteOptions, CommandOptions commandOptions) { return DeleteOneAsync(filter, deleteOptions, commandOptions, false); } - internal async Task DeleteOneAsync(Filter filter, DeleteOptions deleteOptions, CommandOptions commandOptions, bool runSynchronously) + internal async Task DeleteOneAsync(Filter filter, TableDeleteOptions deleteOptions, CommandOptions commandOptions, bool runSynchronously) { + deleteOptions ??= new TableDeleteOptions(); deleteOptions.Filter = filter; var command = CreateCommand("deleteOne").WithPayload(deleteOptions).AddCommandOptions(commandOptions); var response = await command.RunAsyncReturnStatus(runSynchronously).ConfigureAwait(false); return response.Result; } + /// + /// Synchronous version of + public void DeleteMany(Filter filter) + { + DeleteMany(filter, null); + } + + /// + /// Synchronous version of + public void DeleteMany(Filter filter, CommandOptions commandOptions) + { + DeleteManyAsync(filter, commandOptions, true).ResultSync(); + } + /// /// Delete all documents matching the filter from the table. /// /// /// - public Task DeleteManyAsync(Filter filter) + public Task DeleteManyAsync(Filter filter) { return DeleteManyAsync(filter, null); } /// /// - public Task DeleteManyAsync(Filter filter, CommandOptions commandOptions) + public Task DeleteManyAsync(Filter filter, CommandOptions commandOptions) { return DeleteManyAsync(filter, commandOptions, false); } - internal async Task DeleteManyAsync(Filter filter, CommandOptions commandOptions, bool runSynchronously) + internal async Task DeleteManyAsync(Filter filter, CommandOptions commandOptions, bool runSynchronously) { var deleteOptions = new DeleteManyOptions { @@ -884,23 +963,21 @@ internal async Task DeleteManyAsync(Filter filter, CommandOptio throw new BulkOperationException(ex, deleteResult); } } - - return deleteResult; } /// /// Synchronous version of /// /// - public DeleteResult DeleteAll() + public void DeleteAll() { - return DeleteAllAsync().ResultSync(); + DeleteAllAsync().ResultSync(); } /// /// Delete all rows from the table. /// - public Task DeleteAllAsync() + public Task DeleteAllAsync() { return DeleteManyAsync(null, null); } @@ -909,7 +986,7 @@ public Task DeleteAllAsync() /// This is a synchronous version of . /// /// - public Dictionary Alter(IAlterTableOperation operation) + public Table Alter(IAlterTableOperation operation) { return Alter(operation, null); } @@ -918,9 +995,48 @@ public Dictionary Alter(IAlterTableOperation operation) /// This is a synchronous version of . /// /// - public Dictionary Alter(IAlterTableOperation operation, CommandOptions commandOptions) + public Table Alter(IAlterTableOperation operation, CommandOptions commandOptions) + { + var response = AlterAsync(operation, commandOptions, true).ResultSync(); + return response; + } + + /// + /// Alters a table using the specified operation. + /// + /// The alteration operation to apply. + /// The status result of the alterTable command. + public Task> AlterAsync(IAlterTableOperation operation) + { + return AlterAsync(operation, null, false); + } + + /// + /// The alteration operation to apply. + /// Options to customize the command execution. + public Task> AlterAsync(IAlterTableOperation operation, CommandOptions commandOptions) + { + return AlterAsync(operation, commandOptions, false); + } + + /// + /// This is a synchronous version of . + /// + /// + public Table Alter(IAlterTableOperation operation) + where TRowAfterAlter : class + { + return Alter(operation, null); + } + + /// + /// This is a synchronous version of . + /// + /// + public Table Alter(IAlterTableOperation operation, CommandOptions commandOptions) + where TRowAfterAlter : class { - var response = AlterAsync(operation, commandOptions, true).ResultSync(); + var response = AlterAsync(operation, commandOptions, true).ResultSync(); return response; } @@ -929,19 +1045,23 @@ public Dictionary Alter(IAlterTableOperation operation, CommandOpti /// /// The alteration operation to apply. /// The status result of the alterTable command. - public Task> AlterAsync(IAlterTableOperation operation) + public Task> AlterAsync(IAlterTableOperation operation) + where TRowAfterAlter : class { - return AlterAsync(operation, null, false); + return AlterAsync(operation, null, false); } /// + /// The alteration operation to apply. /// Options to customize the command execution. - public Task> AlterAsync(IAlterTableOperation operation, CommandOptions commandOptions) + public Task> AlterAsync(IAlterTableOperation operation, CommandOptions commandOptions) + where TRowAfterAlter : class { - return AlterAsync(operation, commandOptions, false); + return AlterAsync(operation, commandOptions, false); } - internal async Task> AlterAsync(IAlterTableOperation operation, CommandOptions commandOptions, bool runSynchronously) + internal async Task> AlterAsync(IAlterTableOperation operation, CommandOptions commandOptions, bool runSynchronously) + where TRowAfterAlter : class { var payload = new { @@ -952,8 +1072,16 @@ internal async Task> AlterAsync(IAlterTableOperation ope .WithPayload(payload) .AddCommandOptions(commandOptions); - var result = await command.RunAsyncReturnStatus>(runSynchronously).ConfigureAwait(false); - return result.Result; + await command.RunAsyncReturnStatus>(runSynchronously).ConfigureAwait(false); + + return new Table(_tableName, _database, _commandOptions); + + } + + private List GetOptionsTree() + { + var optionsTree = _commandOptions == null ? _database.OptionsTree : _database.OptionsTree.Concat(new[] { _commandOptions }); + return optionsTree.ToList(); } private List GetOptionsTree() diff --git a/src/DataStax.AstraDB.DataApi/Tables/TableDefinition.cs b/src/DataStax.AstraDB.DataApi/Tables/TableDefinition.cs index c27a4a9..bdaa5e9 100644 --- a/src/DataStax.AstraDB.DataApi/Tables/TableDefinition.cs +++ b/src/DataStax.AstraDB.DataApi/Tables/TableDefinition.cs @@ -24,95 +24,25 @@ namespace DataStax.AstraDB.DataApi.Tables; - +/// +/// Definition for creating a table +/// public class TableDefinition { - public TableDefinition() - { } - /* -"definition": { -"columns": { - "title": { - "type": "text" - }, - "number_of_pages": { - "type": "int" - }, - "rating": { - "type": "float" - }, - "metadata": { - "type": "map", - "keyType": "text", - "valueType": "text" - }, - "genres": { - "type": "set", - "valueType": "text" - }, - "is_checked_out": { - "type": "boolean" - }, - "due_date": { - "type": "date" - }, - "example_vector": { - "type": "vector", - "dimension": 1024 - }, - # This column will store vector embeddings. - # The {embedding-provider-name} integration - # will automatically generate vector embeddings - # for any text inserted to this column. - "example_vector": { - "type": "vector", - "dimension": MODEL_DIMENSIONS, - "service": { - "provider": "PROVIDER", - "modelName": "MODEL_NAME", - "authentication": { - "providerKey": "API_KEY_NAME" - }, - "parameters": PARAMETERS - } - }, - # If you want to store the original text - # in addition to the generated embeddings - # you must create a separate column. - "original_text": "text" -}, -"primaryKey": "title" -} -*/ + /// + /// The columns for this table + /// [JsonPropertyName("columns")] [JsonInclude] public Dictionary Columns { get; set; } = new Dictionary(); + /// + /// The primary key definition for this table + /// [JsonPropertyName("primaryKey")] [JsonInclude] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public PrimaryKeyDefinition PrimaryKey { get; set; } - /* - SINGLE COLUMN PRIMARY KEY - "primaryKey": "title" - COMPOSITE PRIMARY KEY - "primaryKey": { - "partitionBy": [ - "title", "rating" - ] - } - COMPOUND PRIMARY KEY - "primaryKey": { - "partitionBy": [ - "title", - "rating" - ], - "partitionSort": { - "number_of_pages": 1, - "is_checked_out": -1 - } - } - */ internal static TableDefinition CreateTableDefinition() where T : new() { @@ -207,7 +137,6 @@ COMPOUND PRIMARY KEY return definition; } - private static void CreateColumnFromPropertyType(string columnName, Type propertyType, TableDefinition definition) { switch (Type.GetTypeCode(propertyType)) @@ -325,66 +254,41 @@ internal static string GetColumnTypeName(Type type) TypeCode.Boolean => "boolean", TypeCode.DateTime => "date", TypeCode.Decimal => "decimal", - // TypeCode.Object => "object", - // TypeCode.Byte => throw new NotImplementedException(), - // TypeCode.Char => throw new NotImplementedException(), - // TypeCode.DBNull => throw new NotImplementedException(), - // TypeCode.Double => throw new NotImplementedException(), - // TypeCode.Empty => throw new NotImplementedException(), - // TypeCode.Int16 => throw new NotImplementedException(), - // TypeCode.Int64 => throw new NotImplementedException(), - // TypeCode.SByte => throw new NotImplementedException(), - // TypeCode.Single => throw new NotImplementedException(), - // TypeCode.UInt16 => throw new NotImplementedException(), - // TypeCode.UInt32 => throw new NotImplementedException(), - // TypeCode.UInt64 => throw new NotImplementedException(), _ => "text", }; } - // return typeValue switch - // { - // "text" => JsonSerializer.Deserialize(jsonText, options), - // "ascii" => JsonSerializer.Deserialize(jsonText, options), - // "varchar" => JsonSerializer.Deserialize(jsonText, options), - // "inet" => JsonSerializer.Deserialize(jsonText, options), - // "int" => JsonSerializer.Deserialize(jsonText, options), - // "tinyint" => JsonSerializer.Deserialize(jsonText, options), - // "smallint" => JsonSerializer.Deserialize(jsonText, options), - // "varint" => JsonSerializer.Deserialize(jsonText, options), - // "bigint" => JsonSerializer.Deserialize(jsonText, options), - // "decimal" => JsonSerializer.Deserialize(jsonText, options), - // "double" => JsonSerializer.Deserialize(jsonText, options), - // "float" => JsonSerializer.Deserialize(jsonText, options), - // "map" => JsonSerializer.Deserialize(jsonText, options), - // "set" => JsonSerializer.Deserialize(jsonText, options), - // "list" => JsonSerializer.Deserialize(jsonText, options), - // "boolean" => JsonSerializer.Deserialize(jsonText, options), - // "date" => JsonSerializer.Deserialize(jsonText, options), - // "time" => JsonSerializer.Deserialize(jsonText, options), - // "timestamp" => JsonSerializer.Deserialize(jsonText, options), - // "vector" => JsonSerializer.Deserialize(jsonText, options), - // "uuid" => JsonSerializer.Deserialize(jsonText, options), - // "blob" => JsonSerializer.Deserialize(jsonText, options), - // _ => throw new JsonException($"Unknown Column type '{typeValue}' encountered.") - // }; } -//TODO: standardize when we use enums with attributes specifying how to serialize, enums with tostring() extension methods, and constants. - internal class ColumnTypeConstants { internal const string Text = "text"; } +/// +/// Extension methods for building table definitions +/// public static class TableDefinitionExtensions { + /// + /// Add a single column primary key to the table definition + /// + /// + /// + /// public static TableDefinition AddSinglePrimaryKey(this TableDefinition tableDefinition, string keyName) { return tableDefinition.AddCompoundPrimaryKey(keyName, 1); } + /// + /// Add a composite primary key to the table definition + /// + /// + /// + /// + /// public static TableDefinition AddCompositePrimaryKey(this TableDefinition tableDefinition, string[] keyNames) { if (keyNames == null || keyNames.Length == 0) @@ -401,6 +305,14 @@ public static TableDefinition AddCompositePrimaryKey(this TableDefinition tableD return tableDefinition; } + /// + /// Add a compound primary key to the table definition with partition key sorts + /// + /// + /// + /// + /// + /// public static TableDefinition AddCompoundPrimaryKey(this TableDefinition tableDefinition, string[] keyNames, PrimaryKeySort[] partitionSorts) { if (keyNames == null || keyNames.Length == 0) @@ -437,48 +349,102 @@ internal static TableDefinition AddCompoundPrimaryKeySort(this TableDefinition t return tableDefinition; } + /// + /// Add a text column to the table definition + /// + /// + /// + /// public static TableDefinition AddTextColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new TextColumn()); return tableDefinition; } + /// + /// Add an int column to the table definition + /// + /// + /// + /// public static TableDefinition AddIntColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new IntColumn()); return tableDefinition; } + /// + /// Add a long column to the table definition + /// + /// + /// + /// public static TableDefinition AddLongColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new LongColumn()); return tableDefinition; } + /// + /// Add a float column to the table definition + /// + /// + /// + /// public static TableDefinition AddFloatColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new FloatColumn()); return tableDefinition; } + /// + /// Add a boolean column to the table definition + /// + /// + /// + /// public static TableDefinition AddBooleanColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new BooleanColumn()); return tableDefinition; } + /// + /// Add a date column to the table definition + /// + /// + /// + /// public static TableDefinition AddDateColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new DateTimeColumn()); return tableDefinition; } + /// + /// Add a vector column to the table definition + /// + /// + /// + /// + /// public static TableDefinition AddVectorColumn(this TableDefinition tableDefinition, string columnName, int dimension) { tableDefinition.Columns.Add(columnName, new VectorColumn(dimension)); return tableDefinition; } + /// + /// Add a vectorize column to the table definition + /// + /// + /// + /// + /// + /// + /// + /// + /// public static TableDefinition AddVectorizeColumn(this TableDefinition tableDefinition, string columnName, int dimension, string provider, string modelName, Dictionary authentication, Dictionary parameters) { tableDefinition.Columns.Add(columnName, new VectorizeColumn(dimension, new VectorServiceOptions @@ -492,66 +458,151 @@ public static TableDefinition AddVectorizeColumn(this TableDefinition tableDefin return tableDefinition; } + /// + /// Add a vectorize column to the table definition + /// + /// + /// + /// + /// + /// public static TableDefinition AddVectorizeColumn(this TableDefinition tableDefinition, string columnName, int dimension, VectorServiceOptions options) { tableDefinition.Columns.Add(columnName, new VectorizeColumn(dimension, options)); return tableDefinition; } + /// + /// Add a vectorize column to the table definition + /// + /// + /// + /// + /// + public static TableDefinition AddVectorizeColumn(this TableDefinition tableDefinition, string columnName, VectorServiceOptions options) + { + tableDefinition.Columns.Add(columnName, new VectorizeColumn(options)); + return tableDefinition; + } + + /// + /// Add a decimal column to the table definition + /// + /// + /// + /// public static TableDefinition AddDecimalColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new DecimalColumn()); return tableDefinition; } + /// + /// Add a double column to the table definition + /// + /// + /// + /// public static TableDefinition AddDoubleColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new DoubleColumn()); return tableDefinition; } + /// + /// Add a UUID column to the table definition + /// + /// + /// + /// public static TableDefinition AddUUIDColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new GuidColumn()); return tableDefinition; } + /// + /// Add a blob column to the table definition + /// + /// + /// + /// public static TableDefinition AddBlobColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new BlobColumn()); return tableDefinition; } + /// + /// Add a GUID column to the table definition + /// + /// + /// + /// public static TableDefinition AddGuidColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new GuidColumn()); return tableDefinition; } + /// + /// Add an IP Address column to the table definition + /// + /// + /// + /// public static TableDefinition AddIPAddressColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new IPAddressColumn()); return tableDefinition; } + /// + /// Add a Duration column to the table definition + /// + /// + /// + /// public static TableDefinition AddDurationColumn(this TableDefinition tableDefinition, string columnName) { tableDefinition.Columns.Add(columnName, new DurationColumn()); return tableDefinition; } + /// + /// Add a dictionary column to the table definition + /// + /// + /// + /// + /// + /// public static TableDefinition AddDictionaryColumn(this TableDefinition tableDefinition, string columnName, Type keyType, Type valueType) { tableDefinition.Columns.Add(columnName, new DictionaryColumn(TableDefinition.GetColumnTypeName(keyType), TableDefinition.GetColumnTypeName(valueType))); return tableDefinition; } + /// + /// Add a set column to the table definition + /// + /// + /// + /// + /// public static TableDefinition AddSetColumn(this TableDefinition tableDefinition, string columnName, Type valueType) { tableDefinition.Columns.Add(columnName, new SetColumn(TableDefinition.GetColumnTypeName(valueType))); return tableDefinition; } + /// + /// Add a list column to the table definition + /// + /// + /// + /// + /// public static TableDefinition AddListColumn(this TableDefinition tableDefinition, string columnName, Type valueType) { tableDefinition.Columns.Add(columnName, new ListColumn(TableDefinition.GetColumnTypeName(valueType))); diff --git a/src/DataStax.AstraDB.DataApi/Tables/TableInsertOneResult.cs b/src/DataStax.AstraDB.DataApi/Tables/TableInsertOneResult.cs new file mode 100644 index 0000000..e3113c3 --- /dev/null +++ b/src/DataStax.AstraDB.DataApi/Tables/TableInsertOneResult.cs @@ -0,0 +1,34 @@ +/* + * Copyright DataStax, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using DataStax.AstraDB.DataApi.Core.Results; +using DataStax.AstraDB.DataApi.SerDes; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace DataStax.AstraDB.DataApi.Tables; + +[JsonConverter(typeof(TableInsertOneResultConverter))] +public class TableInsertOneResult : TableInsertManyResult +{ + + /// + /// A list of the Ids of the inserted documents + /// + [JsonPropertyName("insertedIds")] + public object InsertedId => InsertedIds.Count > 0 ? InsertedIds[0] : null; + +} \ No newline at end of file diff --git a/src/DataStax.AstraDB.DataApi/Tables/TableVectorIndexDefinition.cs b/src/DataStax.AstraDB.DataApi/Tables/TableVectorIndexDefinition.cs index f2db9b4..792c514 100644 --- a/src/DataStax.AstraDB.DataApi/Tables/TableVectorIndexDefinition.cs +++ b/src/DataStax.AstraDB.DataApi/Tables/TableVectorIndexDefinition.cs @@ -14,6 +14,7 @@ * limitations under the License. */ +using DataStax.AstraDB.DataApi.Core; using DataStax.AstraDB.DataApi.Utils; using System; using System.Collections.Generic; @@ -22,8 +23,16 @@ namespace DataStax.AstraDB.DataApi.Tables; +/// +/// Definition of a vector index on a table +/// +/// +/// public class TableVectorIndexDefinition : TableVectorIndexDefinition { + /// + /// The column to create the vector index on + /// public Expression> Column { set @@ -33,38 +42,39 @@ public Expression> Column } } +/// +/// Definition of a vector index on a table +/// public class TableVectorIndexDefinition { - /* - { - "definition": { - "column": "example_column", - "options": { - "caseSensitive": false, - "normalize": true, - "ascii": false - } - } -} - */ + /// + /// The name of the column to create the vector index on + /// [JsonPropertyName("column")] public string ColumnName { get; set; } [JsonInclude] [JsonPropertyName("options")] - internal Dictionary Options { get; set; } = new Dictionary(); + internal Dictionary Options { get; set; } = new Dictionary(); + /// + /// The similarity metric to use + /// [JsonIgnore] - public string Metric + public SimilarityMetric Metric { - get { return Options["metric"]; } + get { return (SimilarityMetric)Options["metric"]; } set { Options["metric"] = value; } } + + /// + /// The source model + /// [JsonIgnore] public string SourceModel { - get { return Options["sourceModel"]; } + get { return (string)Options["sourceModel"]; } set { Options["sourceModel"] = value; } } diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/AssemblyInfo.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/AssemblyInfo.cs index bc8df96..d296ff0 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/AssemblyInfo.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/AssemblyInfo.cs @@ -1 +1,4 @@ -[assembly: Xunit.AssemblyFixture(typeof(DataStax.AstraDB.DataApi.IntegrationTests.Fixtures.AssemblyFixture))] +using Xunit; + +[assembly: CollectionBehavior(MaxParallelThreads = 4)] +[assembly: AssemblyFixture(typeof(DataStax.AstraDB.DataApi.IntegrationTests.Fixtures.AssemblyFixture))] diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Fixtures/TablesFixture.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Fixtures/TablesFixture.cs index 562e67c..c67786a 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Fixtures/TablesFixture.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Fixtures/TablesFixture.cs @@ -96,7 +96,8 @@ await table.CreateVectorIndexAsync(new TableVectorIndex() IndexName = "author_index", Definition = new TableVectorIndexDefinition() { - Column = (b) => b.Author + Column = (b) => b.Author, + Metric = SimilarityMetric.Cosine, } }); await table.CreateIndexAsync(new TableIndex() diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/SearchTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/SearchTests.cs index 7a41baa..f8b0d1a 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/SearchTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/SearchTests.cs @@ -162,6 +162,62 @@ public void SimpleExpressionFilter() Assert.True(!expectedArray.Except(actualArray).Any() && !actualArray.Except(expectedArray).Any()); } + [Fact] + public async Task VectorizeFindOne() + { + var collectionName = "collectionFindOneWithVectorize"; + try + { + List items = new List() { + new() + { + Id = 0, + Name = "This is about a cat.", + }, + new() + { + Id = 1, + Name = "This is about a dog.", + }, + new() + { + Id = 2, + Name = "This is about a horse.", + }, + }; + + var options = new CollectionDefinition + { + Vector = new VectorOptions + { + Metric = SimilarityMetric.Cosine, + Service = new VectorServiceOptions + { + Provider = "nvidia", + ModelName = "NV-Embed-QA" + } + } + }; + var collection = await fixture.Database.CreateCollectionAsync(collectionName, options); + var insertResult = await collection.InsertManyAsync(items); + Assert.Equal(items.Count, insertResult.InsertedIds.Count); + var findOptions = new DocumentFindOptions() + { + Sort = Builders.Sort.Vectorize("dog"), + IncludeSimilarity = true + }; + + var result = await collection.FindOneAsync(findOptions); + Assert.NotNull(result); + Assert.NotNull(result.Similarity); + Assert.Equal(1, result.Id); + } + finally + { + await fixture.Database.DropCollectionAsync(collectionName); + } + } + [Fact] public void Limit_RunsAsync_ReturnsLimitedResult() { diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableAlterTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableAlterTests.cs index bc4f945..23afb37 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableAlterTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableAlterTests.cs @@ -30,11 +30,11 @@ public async Task AlterTableAddColumns() ["review_notes"] = new AlterTableColumnDefinition { Type = "text" } }; - await table.AlterAsync(new AlterTableAddColumns(newColumns), null, runSynchronously: false); + await table.AlterAsync(new AlterTableAddColumns(newColumns), null); //throws error on dupe var ex = await Assert.ThrowsAsync(() => - table.AlterAsync(new AlterTableAddColumns(newColumns), null, runSynchronously: false)); + table.AlterAsync(new AlterTableAddColumns(newColumns), null)); Assert.Contains("unique", ex.Message, StringComparison.OrdinalIgnoreCase); } @@ -68,7 +68,7 @@ public async Task AlterTableAddColumnsMapSet() }; - await table.AlterAsync(new AlterTableAddColumns(newColumns), null, runSynchronously: false); + await table.AlterAsync(new AlterTableAddColumns(newColumns)); } finally { @@ -97,7 +97,7 @@ await table.AlterAsync(new AlterTableAddVectorColumns(new Dictionary { @@ -199,7 +199,7 @@ await table.AlterAsync(new AlterTableAddVectorize(new Dictionary { - ["plot_synopsis_vectorize_drop"] = new AlterTableVectorColumnDefinition + ["plot_synopsis_vector_drop"] = new AlterTableVectorColumnDefinition { VectorDimension = 1024 } - }), null, false); + })); await table.AlterAsync(new AlterTableAddVectorize(new Dictionary { - ["plot_synopsis_vectorize_drop"] = new VectorServiceOptions + ["plot_synopsis_vector_drop"] = new VectorServiceOptions { Provider = "nvidia", ModelName = "NV-Embed-QA" } + })); - }), null, false); + var dropVectorize = new AlterTableDropVectorize(new[] { "plot_synopsis_vector_drop" }); + await table.AlterAsync(dropVectorize); - var dropVectorize = new AlterTableDropVectorize(new[] { "plot_synopsis_vectorize_drop" }); - await table.AlterAsync(dropVectorize, null, runSynchronously: false); - - var dropColumn = new AlterTableDropColumns(new[] { "plot_synopsis_vectorize_drop" }); - await table.AlterAsync(dropColumn, null, runSynchronously: false); + } + catch (Exception ex) + { + Console.WriteLine(ex); + throw; } finally { diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs index 5d548ef..7c86545 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs @@ -221,8 +221,7 @@ public async Task Update_Test() var update = Builders.Update.Set(x => x.Rating, 3.07) .Set(x => x.Genres, new HashSet { "SetItem1", "SetItem2" }) .Unset(x => x.DueDate); - var result = await table.UpdateOneAsync(filter, update); - Assert.Equal(1, result.ModifiedCount); + await table.UpdateOneAsync(filter, update); var updatedDocument = await table.FindOneAsync(filter); Assert.Equal(3.07f, updatedDocument.Rating); Assert.Equal(new HashSet { "SetItem1", "SetItem2" }, updatedDocument.Genres); @@ -280,7 +279,7 @@ await table.CreateIndexAsync(new TableIndex() .Eq(so => so.Title, "Title 1"); var findResult = await table.FindOneAsync(filter); Assert.Equal("Title 1", findResult.Title); - var result = await table.DeleteOneAsync(filter); + await table.DeleteOneAsync(filter); var deletedResult = await table.FindOneAsync(filter); Assert.Null(deletedResult); } @@ -341,7 +340,7 @@ await table.CreateIndexAsync(new TableIndex() .Eq(so => so.Title, "Title 1"); var findResult = table.Find(filter).ToList(); Assert.Single(findResult); - var result = await table.DeleteManyAsync(filter); + await table.DeleteManyAsync(filter); var deletedResult = table.Find(filter).ToList(); Assert.Empty(deletedResult); } @@ -376,7 +375,7 @@ public async Task Delete_CompositePrimaryKey() }); var findResult = table.Find(filter).ToList(); Assert.Single(findResult); - var result = await table.DeleteManyAsync(filter); + await table.DeleteManyAsync(filter); var deletedResult = table.Find(filter).ToList(); Assert.Empty(deletedResult); } @@ -422,7 +421,7 @@ public async Task Delete_CompoundPrimaryKey() }); var findResult = table.Find(filter).ToList(); Assert.Single(findResult); - var result = await table.DeleteManyAsync(filter); + await table.DeleteManyAsync(filter); var deletedResult = table.Find(filter).ToList(); Assert.Empty(deletedResult); } @@ -454,7 +453,7 @@ public async Task Delete_All() await table.InsertManyAsync(rows); var findResult = table.Find().ToList(); Assert.Equal(rows.Count, findResult.Count); - var result = await table.DeleteAllAsync(); + await table.DeleteAllAsync(); var deletedResult = table.Find().ToList(); Assert.Empty(deletedResult); } @@ -583,16 +582,14 @@ public async Task Update_Test_Untyped() { var filter = Builders.Filter.Eq("Id", 3); var update = Builders.Update.Set("Name", "Name_3_Updated"); - var result = await fixture.UntypedTableSinglePrimaryKey.UpdateOneAsync(filter, update); - Assert.Equal(1, result.ModifiedCount); + await fixture.UntypedTableSinglePrimaryKey.UpdateOneAsync(filter, update); var updatedDocument = await fixture.UntypedTableSinglePrimaryKey.FindOneAsync(filter); Assert.Equal("Name_3_Updated", updatedDocument["Name"].ToString()); filter = Builders.Filter.CompositeKey( new PrimaryKeyFilter("Id", 3), new PrimaryKeyFilter("IdTwo", "IdTwo_3")); - result = await fixture.UntypedTableCompositePrimaryKey.UpdateOneAsync(filter, update); - Assert.Equal(1, result.ModifiedCount); + await fixture.UntypedTableCompositePrimaryKey.UpdateOneAsync(filter, update); updatedDocument = await fixture.UntypedTableCompositePrimaryKey.FindOneAsync(filter); Assert.Equal("Name_3_Updated", updatedDocument["Name"].ToString()); @@ -605,8 +602,7 @@ public async Task Update_Test_Untyped() Builders.Filter.Eq("SortOneAscending", "SortOneAscending3"), Builders.Filter.Eq("SortTwoDescending", "SortTwoDescending47") }); - result = await fixture.UntypedTableCompoundPrimaryKey.UpdateOneAsync(filter, update); - Assert.Equal(1, result.ModifiedCount); + await fixture.UntypedTableCompoundPrimaryKey.UpdateOneAsync(filter, update); updatedDocument = await fixture.UntypedTableCompoundPrimaryKey.FindOneAsync(filter); Assert.Equal("Name_3_Updated", updatedDocument["Name"].ToString()); } diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/readme.md b/test/DataStax.AstraDB.DataApi.IntegrationTests/readme.md index ccf7ad4..c8586c9 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/readme.md +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/readme.md @@ -6,7 +6,7 @@ export ASTRA_DB_TOKEN="your_token_here" export ASTRA_DB_URL="your_db_url_here" ``` -dotnet test --collect:"XPlat Code Coverage" +dotnet test -- "xUnit.MaxParallelThreads=4" reportgenerator -reports:"Path\To\TestProject\TestResults\{guid}\coverage.cobertura.xml"