Cvičení – implementace služby Azure Cosmos DB for NoSQL
SlužbaCosmosDbService
Azure Cosmos DB spravuje dotazování, vytváření, odstraňování a aktualizaci relací a zpráv v aplikaci pomocníka s AI. Ke správě všech těchto operací je služba nutná k implementaci více metod pro každou potenciální operaci pomocí různých funkcí sady .NET SDK.
V tomto cvičení je potřeba splnit několik klíčových požadavků:
- Implementace operací pro vytvoření relace nebo zprávy
- Implementace dotazů pro načtení více relací nebo zpráv
- Implementace operace pro aktualizaci jedné relace nebo dávkové aktualizace více zpráv
- Implementace operace pro dotazování a odstranění více souvisejících relací a zpráv
Vytvoření relace nebo zprávy
Azure Cosmos DB for NoSQL ukládá data ve formátu JSON, což nám umožňuje ukládat mnoho typů dat do jednoho kontejneru. Tato aplikace ukládá chat "session" s asistentem AI i jednotlivými "zprávami" v rámci každé relace. S rozhraním API pro NoSQL může aplikace ukládat oba typy dat do stejného kontejneru a pak rozlišovat mezi těmito typy pomocí jednoduchého type
pole.
Otevřete soubor Services/CosmosDbService.cs.
V rámci
InsertSessionAsync
této metody odeberte veškerý existující zástupný kód.public async Task<Session> InsertSessionAsync(Session session) { }
Vytvořte novou proměnnou s názvem
partitionKey
typuPartitionKey
pomocí vlastnosti aktuální relaceSessionId
jako parametru.PartitionKey partitionKey = new(session.SessionId);
CreateItemAsync
Vyvolá metodu kontejneru předávajícíhosession
parametr apartitionKey
proměnnou. Vrátí odpověď jako výsledekInsertSessionAsync
metody.return await _container.CreateItemAsync<Session>( item: session, partitionKey: partitionKey );
V rámci
InsertMessageAsync
této metody odeberte veškerý existující zástupný kód.public async Task<Message> InsertMessageAsync(Message message) { }
Vytvořte proměnnou
PartitionKey
jakosession.SessionId
hodnotu klíče oddílu.PartitionKey partitionKey = new(message.SessionId);
Vytvořte novou proměnnou zprávy s názvem
newMessage
Timestamp
vlastnosti aktualizovanou na aktuální časové razítko UTC.Message newMessage = message with { TimeStamp = DateTime.UtcNow };
Vyvolání předávání
CreateItemAsync
proměnných nové zprávy i klíče oddílu. Vrátí odpověď jako výsledek funkceInsertMessageAsync
.return await _container.CreateItemAsync<Message>( item: newMessage, partitionKey: partitionKey );
Uložte soubor Služby/CosmosDbService.cs.
Načtení více relací nebo zpráv
Existují dva hlavní případy použití, kdy aplikace potřebuje načíst více položek z našeho kontejneru. Nejprve aplikace načte všechny relace pro aktuálního uživatele filtrováním položek na ty, kde type = Session
. Za druhé, aplikace načte všechny zprávy pro relaci provedením podobného filtru, kde type = Session & sessionId = <current-session-id>
. Tady implementujte oba dotazy pomocí sady .NET SDK a iterátoru informačního kanálu.
V rámci
GetSessionsAsync
této metody odeberte veškerý existující zástupný kód.public async Task<List<Session>> GetSessionsAsync() { }
Vytvořte novou proměnnou s názvem
query
typuQueryDefinition
pomocí dotazuSELECT DISTINCT * FROM c WHERE c.type = @type
SQL . Pomocí fluentWithParameter
metody přiřaďte názevSession
třídy jako hodnotu parametru.QueryDefinition query = new QueryDefinition("SELECT DISTINCT * FROM c WHERE c.type = @type") .WithParameter("@type", nameof(Session));
Vyvolá obecnou metodu
GetItemQueryIterator<>
_container
pro proměnnou, která předává obecný typSession
aquery
proměnnou jako parametr. Uložte výsledek do proměnné typuFeedIterator<Session>
s názvemresponse
.FeedIterator<Session> response = _container.GetItemQueryIterator<Session>(query);
Vytvořte novou obecnou proměnnou seznamu s názvem
output
.List<Session> output = new();
Vytvořte smyčku While, která se spustí, dokud
response.HasMoreResults
nebude splněna.while (response.HasMoreResults) { }
Poznámka:
Použití smyčky While zde efektivně prochází všechny stránky vaší odpovědi, dokud nezůstane žádné stránky.
Ve smyčce While asynchronně získejte další stránku výsledků vyvoláním
ReadNextAsync
response
proměnné a následným přidáním těchto výsledků do proměnné seznamu s názvemoutput
.FeedResponse<Session> results = await response.ReadNextAsync(); output.AddRange(results);
Mimo smyčku While vraťte
output
proměnnou se seznamem relací jako výsledekGetSessionsAsync
metody.return output;
V rámci
GetSessionMessagesAsync
této metody odeberte veškerý existující zástupný kód.public async Task<List<Message>> GetSessionMessagesAsync(string sessionId) { }
Vytvořte proměnnou
query
typuQueryDefinition
. Použijte dotazSELECT * FROM c WHERE c.sessionId = @sessionId AND c.type = @type
SQL . Pomocí fluentWithParameter
metody přiřaďte@sessionId
parametr identifikátoru relace předaného jako parametr a@type
parametr názvuMessage
třídy.QueryDefinition query = new QueryDefinition("SELECT * FROM c WHERE c.sessionId = @sessionId AND c.type = @type") .WithParameter("@sessionId", sessionId) .WithParameter("@type", nameof(Message));
Vytvořte
FeedIterator<Message>
pomocíquery
proměnné aGetItemQueryIterator<>
metody.FeedIterator<Message> response = _container.GetItemQueryIterator<Message>(query);
K iteraci všech stránek výsledků použijte smyčku While a výsledky uložte do jedné
List<Message>
proměnné s názvemoutput
.List<Message> output = new(); while (response.HasMoreResults) { FeedResponse<Message> results = await response.ReadNextAsync(); output.AddRange(results); }
Vrátí proměnnou
output
jako výsledekGetSessionMessagesAsync
metody.return output;
Uložte soubor Služby/CosmosDbService.cs.
Aktualizace jedné nebo více relací nebo zpráv
Existují scénáře, kdy jedna relace vyžaduje aktualizaci nebo více než jedna zpráva vyžaduje aktualizaci. V prvním scénáři použijte ReplaceItemAsync
metodu sady SDK k nahrazení existující položky upravenou verzí. Pro druhý scénář použijte transakční dávkovou funkci sady SDK k úpravě více zpráv v jedné dávce.
V rámci
UpdateSessionAsync
této metody odeberte veškerý existující zástupný kód.public async Task<Session> UpdateSessionAsync(Session session) { }
Vytvořte proměnnou
PartitionKey
jakosession.SessionId
hodnotu klíče oddílu.PartitionKey partitionKey = new(session.SessionId);
Vyvolání předání
ReplaceItemAsync
jedinečného identifikátoru a klíče oddílu nové zprávy. Vrátí odpověď jako výsledek funkceUpdateSessionAsync
.return await _container.ReplaceItemAsync( item: session, id: session.Id, partitionKey: partitionKey );
V rámci
UpsertSessionBatchAsync
této metody odeberte veškerý existující zástupný kód.public async Task UpsertSessionBatchAsync(params dynamic[] messages) { }
pomocí jazyka integrovaného dotazu (LINQ) ověřte, že všechny zprávy obsahují jeden identifikátor relace (
SessionId
LINQ). Pokud některá ze zpráv obsahuje jinou hodnotu, vyvoláte výjimkuArgumentException
.if (messages.Select(m => m.SessionId).Distinct().Count() > 1) { throw new ArgumentException("All items must have the same partition key."); }
Vytvořte novou
PartitionKey
proměnnou pomocíSessionId
vlastnosti první zprávy.PartitionKey partitionKey = new(messages.First().SessionId);
Poznámka:
Nezapomeňte, že můžete bezpečně předpokládat, že všechny zprávy mají stejný identifikátor relace, pokud se aplikace přesunula do tohoto bodu v kódu metody.
Vytvořte novou proměnnou s názvem
batch
typuTransactionalBatch
vyvolánímCreateTransactionalBatch
metody_container
proměnné. Pro dávkové operace použijte aktuální proměnnou klíče oddílu.TransactionalBatch batch = _container.CreateTransactionalBatch(partitionKey);
Důležité
Nezapomeňte, že všechny transakce v této dávce by měly být ve stejném logickém oddílu.
Iterujte přes každou zprávu v
messages
poli pomocí smyčky foreach.foreach (var message in messages) { }
Ve smyčce foreach přidejte každou zprávu jako operaci upsertu do dávky.
batch.UpsertItem( item: message );
Poznámka:
Upsert informuje službu Azure Cosmos DB, aby určila, zda má být položka nahrazena nebo aktualizována na straně serveru. Azure Cosmos DB toto rozhodnutí určí pomocí klíče oddílu
id
každé položky.Mimo smyčku foreach asynchronně vyvolat
ExecuteAsync
metodu dávky ke spuštění všech operací v dávce.await batch.ExecuteAsync();
Uložte soubor Služby/CosmosDbService.cs.
Odebrání relace a všech souvisejících zpráv
Nakonec zkombinujte dotaz a transakční dávkové funkce, abyste odebrali více položek. V tomto příkladu získejte položku relace a všechny související zprávy dotazováním na všechny položky s konkrétním identifikátorem relace bez ohledu na typ. Pak vytvořte transakční dávku, která odstraní všechny odpovídající položky jako jednu transakci.
V rámci
DeleteSessionAndMessagesAsync
této metody odeberte veškerý existující zástupný kód.public async Task DeleteSessionAndMessagesAsync(string sessionId) { }
Vytvořte proměnnou s názvem
partitionKey
typuPartitionKey
pomocísesionId
řetězcové hodnoty předané jako parametr této metody.PartitionKey partitionKey = new(sessionId);
Pomocí stejného
sessionId
parametru metody vytvořteQueryDefinition
objekt, který najde všechny položky, které odpovídají identifikátoru relace. Použijte parametr dotazu prosessionId
dotaz a ujistěte se, že dotaz nefiltrujete podle typu položky.QueryDefinition query = new QueryDefinition("SELECT VALUE c.id FROM c WHERE c.sessionId = @sessionId") .WithParameter("@sessionId", sessionId);
Poznámka:
Pokud v tomto dotazu použijete
type
filtr, můžete neúmyslně vynechat související zprávy nebo relace, které by se měly hromadně odebrat jako součást této operace.Vytvořte nový
FeedIterator<string>
příkaz pomocíGetItemQueryIterator
a dotaz, který jste vytvořili.FeedIterator<string> response = _container.GetItemQueryIterator<string>(query);
Vytvořte pojmenovanou
batch
proměnnouTransactionalBatch
usingCreateTransactionalBatch
a klíč oddílu.TransactionalBatch batch = _container.CreateTransactionalBatch(partitionKey);
Vytvořte smyčku While, která bude iterovat všemi stránkami výsledků. Ve smyčce While získejte další stránku výsledků a pomocí smyčky foreach iterujte všechny identifikátory položek na stránce. V rámci smyčky foreach přidejte dávkovou operaci pro odstranění položky pomocí
batch.DeleteItem
.while (response.HasMoreResults) { FeedResponse<string> results = await response.ReadNextAsync(); foreach (var itemId in results) { batch.DeleteItem( id: itemId ); } }
Po smyčce while spusťte dávku pomocí
batch.ExecuteAsync
.await batch.ExecuteAsync();
Uložte soubor Služby/CosmosDbService.cs.
Kontrola práce
Teď má vaše aplikace úplnou implementaci Azure OpenAI a Azure Cosmos DB. Kompletní testování aplikace můžete provést laděním řešení.
Otevřete nový terminál.
Spusťte aplikaci s povoleným opětovným načítáním za provozu pomocí
dotnet watch
.dotnet watch run --non-interactive
Visual Studio Code znovu spustí jednoduchý prohlížeč v nástroji se spuštěnou webovou aplikací. Ve webové aplikaci vytvořte novou chatovací relaci a položte asistentovi AI otázku. Pak zavřete spuštěnou webovou aplikaci.
Zavřete terminál. Teď otevřete nový terminál.
Spusťte aplikaci ještě jednou s povoleným opětovným načítáním za provozu pomocí
dotnet watch
.dotnet watch run --non-interactive
Visual Studio Code znovu spustí jednoduchý prohlížeč v nástroji se spuštěnou webovou aplikací. U této iterace sledujte, že relace chatu jsou trvalé mezi relacemi ladění.
Zavřete terminál.