Skip to content

Commit 7a975b9

Browse files
Document Id changes (#14)
Co-authored-by: jeffrey-elliott <jeffrey.elliott@gmail.com> Co-authored-by: Steve Hewitt <45011981+stephenatsembit@users.noreply.github.com>
1 parent 3b12d9d commit 7a975b9

File tree

15 files changed

+314
-36
lines changed

15 files changed

+314
-36
lines changed

index.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ This C# Client Library simplifies using the DataStax Data API to manage and inte
88

99
# Installation
1010

11-
// TODO: NuGet instructions
11+
```
12+
dotnet add package DataStax.AstraDB.DataApi --prerelease
13+
```
1214

1315
# Quickstart
1416

@@ -17,7 +19,7 @@ This C# Client Library simplifies using the DataStax Data API to manage and inte
1719
var client = new DataApiClient("YourTokenHere");
1820
1921
//connect to a database
20-
var database = client.GetDatabase("YourDatabaseUrlHere");
22+
var database = client.GetDatabase("YourAPIEndpointHere");
2123
2224
//create a new collection
2325
var collection = await database.CreateCollectionAsync<SimpleObject>("YourCollectionNameHere");

src/DataStax.AstraDB.DataApi/Core/CollectionDefinition.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17+
using DataStax.AstraDB.DataApi.SerDes;
18+
using System;
19+
using System.Collections.ObjectModel;
20+
using System.Reflection;
1721
using System.Text.Json.Serialization;
1822

1923
namespace DataStax.AstraDB.DataApi.Core;
@@ -40,6 +44,36 @@ public class CollectionDefinition
4044
/// </summary>
4145
[JsonPropertyName("indexing")]
4246
public IndexingOptions Indexing { get; set; }
47+
48+
internal static CollectionDefinition Create<T>()
49+
{
50+
Type type = typeof(T);
51+
PropertyInfo idProperty = null;
52+
DocumentIdAttribute idAttribute = null;
53+
54+
CollectionDefinition definition = new();
55+
56+
foreach (var property in type.GetProperties())
57+
{
58+
var attr = property.GetCustomAttribute<DocumentIdAttribute>();
59+
if (attr != null)
60+
{
61+
idProperty = property;
62+
idAttribute = attr;
63+
break;
64+
}
65+
}
66+
67+
if (idProperty != null)
68+
{
69+
if (idAttribute.DefaultIdType.HasValue)
70+
{
71+
definition.DefaultId = new DefaultIdOptions() { Type = idAttribute.DefaultIdType.Value };
72+
}
73+
}
74+
75+
return definition;
76+
}
4377
}
4478

4579

src/DataStax.AstraDB.DataApi/Core/CommandOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class CommandOptions
4444
/// <summary>
4545
/// The token to use for authentication
4646
/// </summary>
47-
public string Token { get; internal set; }
47+
public string Token { get; set; }
4848

4949
/// <summary>
5050
/// The destination datastore.

src/DataStax.AstraDB.DataApi/Core/Database.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ public class Database
7373
private readonly string _apiEndpoint;
7474
private readonly DataApiClient _client;
7575
private readonly string _urlPostfix = "";
76-
private readonly DatabaseCommandOptions _dbCommandOptions;
7776
private readonly Guid _id;
7877

78+
private DatabaseCommandOptions _dbCommandOptions;
79+
7980
internal string ApiEndpoint => _apiEndpoint;
8081
internal DataApiClient Client => _client;
8182
internal Guid DatabaseId => _id;
@@ -98,6 +99,17 @@ internal Database(string apiEndpoint, DataApiClient client, DatabaseCommandOptio
9899
_id = (Guid)GetDatabaseIdFromUrl(_apiEndpoint);
99100
}
100101

102+
/// <summary>
103+
/// Set the active keyspace to use for all subsequent operations (can be overridden in each method call via an overload with the <see cref="DatabaseCommandOptions"/> parameter)
104+
/// </summary>
105+
/// <param name="keyspace"></param>
106+
public void UseKeyspace(string keyspace)
107+
{
108+
var commandOptions = _dbCommandOptions ?? new DatabaseCommandOptions();
109+
commandOptions.Keyspace = keyspace;
110+
_dbCommandOptions = commandOptions;
111+
}
112+
101113
///<summary>
102114
///Synchronous version of <see cref="DoesCollectionExistAsync(string)"/>.
103115
///</summary>
@@ -409,10 +421,11 @@ public Task<Collection<T, TId>> CreateCollectionAsync<T, TId>(string collectionN
409421

410422
private async Task<Collection<T>> CreateCollectionAsync<T>(string collectionName, CollectionDefinition definition, DatabaseCommandOptions options, bool runSynchronously) where T : class
411423
{
412-
object payload = definition == null ? new
424+
if (definition == null)
413425
{
414-
name = collectionName
415-
} : new
426+
427+
}
428+
object payload = new
416429
{
417430
name = collectionName,
418431
options = definition
@@ -424,10 +437,11 @@ private async Task<Collection<T>> CreateCollectionAsync<T>(string collectionName
424437

425438
private async Task<Collection<T, TId>> CreateCollectionAsync<T, TId>(string collectionName, CollectionDefinition definition, DatabaseCommandOptions options, bool runSynchronously) where T : class
426439
{
427-
object payload = definition == null ? new
440+
if (definition == null)
428441
{
429-
name = collectionName
430-
} : new
442+
definition = CollectionDefinition.Create<T>();
443+
}
444+
object payload = new
431445
{
432446
name = collectionName,
433447
options = definition

src/DataStax.AstraDB.DataApi/DataAPIClient.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,22 @@ public Database GetDatabase(string apiEndpoint)
169169
}
170170

171171
/// <summary>
172-
/// Gets an instance of the <see cref="Database"/> class given the API Endpoint and the keyspace to connect to.
172+
/// Gets an instance of the <see cref="Database"/> class given the API Endpoint of the database to connect to, a token to use, and optionally a keyspace.
173+
/// If the keyspace is not provided the default keyspace will be used.
173174
/// </summary>
174175
/// <param name="apiEndpoint">The API endpoint of the database.</param>
175-
/// <param name="keyspace">The keyspace to connect to.</param>
176+
/// <param name="token">The specific token to use for this database connection.</param>
177+
/// <param name="keyspace">Optional: The keyspace to connect to.</param>
176178
/// <returns>An instance of the <see cref="Database"/> class.</returns>
177179
/// <example>
178180
/// <code>
179181
/// var client = new DataApiClient("token");
180182
/// var database = client.GetDatabase("https://1ae8dd5d-19ce-452d-9df8-6e5b78b82ca7-us-east1.apps.astra.datastax.com", "myKeyspace");
181183
/// </code>
182184
/// </example>
183-
public Database GetDatabase(string apiEndpoint, string keyspace)
185+
public Database GetDatabase(string apiEndpoint, string token, string keyspace = null)
184186
{
185-
var dbOptions = new DatabaseCommandOptions() { Keyspace = keyspace };
187+
var dbOptions = new DatabaseCommandOptions() { Token = token, Keyspace = keyspace };
186188
return GetDatabase(apiEndpoint, dbOptions);
187189
}
188190

@@ -229,7 +231,8 @@ public Database GetDatabase(Guid databaseId)
229231
/// Gets an instance of a <see cref="Database"/> based on the database Id, set to the provided keyspace.
230232
/// </summary>
231233
/// <param name="databaseId">The Guid of the database.</param>
232-
/// <param name="keyspace">The keyspace to use for the database commands.</param>
234+
/// <param name="token">The specific token to use for this database connection.</param>
235+
/// <param name="keyspace">Optional: The keyspace to use for the database commands.</param>
233236
/// <returns>An instance of the <see cref="Database"/> class.</returns>
234237
/// <example>
235238
/// <code>
@@ -241,9 +244,9 @@ public Database GetDatabase(Guid databaseId)
241244
/// Using a Guid instead of the Database API endpoint requires an extra API call to lookup the appropriate database.
242245
/// If you want to avoid this, use an overload that accepts the API endpoint (<see cref="GetDatabase(string, string)"/>).
243246
/// </remarks>
244-
public Database GetDatabase(Guid databaseId, string keyspace)
247+
public Database GetDatabase(Guid databaseId, string token, string keyspace = null)
245248
{
246-
var dbOptions = new DatabaseCommandOptions() { Keyspace = keyspace };
249+
var dbOptions = new DatabaseCommandOptions() { Keyspace = keyspace, Token = token };
247250
return GetDatabase(databaseId, dbOptions);
248251
}
249252

src/DataStax.AstraDB.DataApi/DataStax.AstraDB.DataApi.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<LangVersion>10.0</LangVersion>
88

99
<PackageId>DataStax.AstraDB.DataApi</PackageId>
10-
<Version>1.0.0</Version>
10+
<Version>1.0.2-beta</Version>
1111
<Authors>DataStax</Authors>
1212
<Company>DataStax</Company>
1313
<Description>Client library for accessing the DataStax Astra DB Data API from .NET applications.</Description>
@@ -19,7 +19,7 @@
1919
<RepositoryType>git</RepositoryType>
2020
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
2121
<PackageIcon>packageIcon.png</PackageIcon>
22-
<Readme>README.md</Readme>
22+
<PackageReadmeFile>README.md</PackageReadmeFile>
2323
</PropertyGroup>
2424

2525
<ItemGroup>

src/DataStax.AstraDB.DataApi/SerDes/DocumentConverter.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ static DocumentConverter()
5050
{
5151
DocumentMappingField.Vectorize => DataApiKeywords.Vectorize,
5252
DocumentMappingField.Vector => DataApiKeywords.Vector,
53-
DocumentMappingField.Id => DataApiKeywords.Id,
5453
DocumentMappingField.Similarity => DataApiKeywords.Similarity,
5554
_ => prop.Name
5655
};
@@ -60,7 +59,8 @@ static DocumentConverter()
6059
}
6160
else
6261
{
63-
if (prop.Name == DataApiKeywords.Id)
62+
var idAttr = prop.GetCustomAttribute<DocumentIdAttribute>();
63+
if (idAttr != null || prop.Name == DataApiKeywords.Id)
6464
{
6565
FieldMappings[prop] = DataApiKeywords.Id;
6666
ReverseMappings[DataApiKeywords.Id] = prop;
@@ -131,6 +131,13 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions
131131
continue;
132132
}
133133
}
134+
135+
var documentIdAttr = prop.GetCustomAttribute<DocumentIdAttribute>();
136+
if (documentIdAttr != null && propValue == null)
137+
{
138+
continue;
139+
}
140+
134141
writer.WritePropertyName(propertyName);
135142

136143
JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright DataStax, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
namespace DataStax.AstraDB.DataApi.SerDes;
18+
19+
using DataStax.AstraDB.DataApi.Core;
20+
using System;
21+
22+
/// <summary>
23+
/// Marks a property on a document as the unique ID
24+
/// </summary>
25+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
26+
public class DocumentIdAttribute : Attribute
27+
{
28+
/// <summary>
29+
/// If the database is going to auto-generate ids for inserted document, which type of ID should it generate?
30+
/// </summary>
31+
public DefaultIdType? DefaultIdType { get; }
32+
33+
/// <summary>
34+
/// Initializes a new instance of the <see cref="DocumentIdAttribute"/> class.
35+
/// </summary>
36+
/// <remarks>
37+
/// 1. If you want the database to auto-generate Ids for the documents, please use the <see cref="DocumentIdAttribute(DefaultIdType)"/> overload.
38+
/// When not specified, DefaultIdType.Uuid (UUID v4) will be used.
39+
/// 2. Please note that the C# type used for the property/field that this attribute is assigned to must match the type associated
40+
/// with the specified default ID (or you need to always pass in a value for the Id field).
41+
/// </remarks>
42+
public DocumentIdAttribute()
43+
{
44+
45+
}
46+
47+
/// <summary>
48+
/// Initializes a new instance of the <see cref="DocumentIdAttribute"/> class.
49+
/// </summary>
50+
/// <param name="defaultIdType">The type of Id to auto-generate</param>
51+
/// <remarks>
52+
/// The C# type used for the property/field that this attribute is assigned to must match the type associated
53+
/// with the specified default ID (or use the <see cref="DocumentIdAttribute()"/> constructor to not set a default type
54+
/// and always pass in a value for the Id field.
55+
/// </remarks>
56+
public DocumentIdAttribute(DefaultIdType defaultIdType)
57+
{
58+
DefaultIdType = defaultIdType;
59+
}
60+
}

src/DataStax.AstraDB.DataApi/SerDes/DocumentMappingField.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ namespace DataStax.AstraDB.DataApi.SerDes;
2121
/// </summary>
2222
public enum DocumentMappingField
2323
{
24-
/// <summary>Serializes as "_id" for unique identifiers</summary>
25-
Id,
2624
/// <summary>Serializes as "$vectorize" for a string to vectorize</summary>
2725
Vectorize,
2826
/// <summary>Serializes as "$vector" for vector data.</summary>

src/DataStax.AstraDB.DataApi/Utils/Extensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ private static void BuildPropertyName(MemberExpression memberExpression, StringB
7070
{
7171
name = jsonPropertyNameAttribute.Name;
7272
}
73-
var attribute = propertyInfo.GetCustomAttribute<DocumentMappingAttribute>();
74-
if (attribute != null && attribute.Field == DocumentMappingField.Id)
73+
var attribute = propertyInfo.GetCustomAttribute<DocumentIdAttribute>();
74+
if (attribute != null)
7575
{
7676
name = DataApiKeywords.Id;
7777
}

0 commit comments

Comments
 (0)