تمرين - تنفيذ Azure Cosmos DB لخدمة NoSQL
تدير خدمة Azure Cosmos DB (CosmosDbService
) الاستعلام عن الجلسات والرسائل وإنشائه وحذفه وتحديثه في تطبيق مساعد الذكاء الاصطناعي. لإدارة جميع هذه العمليات، تكون الخدمة مطلوبة لتنفيذ أساليب متعددة لكل عملية محتملة باستخدام ميزات مختلفة من .NET SDK.
هناك متطلبات رئيسية متعددة يجب معالجتها في هذا التمرين:
- تنفيذ العمليات لإنشاء جلسة عمل أو رسالة
- تنفيذ الاستعلامات لاسترداد جلسات عمل أو رسائل متعددة
- تنفيذ عملية لتحديث جلسة عمل واحدة أو تحديث دفعة رسائل متعددة
- تنفيذ عملية للاستعلام عن العديد من الجلسات والرسائل ذات الصلة وحذفها
إنشاء جلسة عمل أو رسالة
يخزن Azure Cosmos DB for NoSQL البيانات بتنسيق JSON مما يسمح لنا بتخزين العديد من أنواع البيانات في حاوية واحدة. يخزن هذا التطبيق كلا من "جلسة" الدردشة مع مساعد الذكاء الاصطناعي و"الرسائل" الفردية داخل كل جلسة عمل. باستخدام واجهة برمجة التطبيقات ل NoSQL، يمكن للتطبيق تخزين كلا النوعين من البيانات في نفس الحاوية ثم التمييز بين هذه الأنواع باستخدام حقل بسيط type
.
افتح ملف Services/CosmosDbService.cs .
InsertSessionAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task<Session> InsertSessionAsync(Session session) { }
إنشاء متغير جديد يسمى
partitionKey
من النوعPartitionKey
باستخدام خاصية جلسة العملSessionId
الحالية كمعلمة.PartitionKey partitionKey = new(session.SessionId);
CreateItemAsync
استدعاء أسلوب الحاوية التي تمر في المعلمةsession
والمتغيرpartitionKey
. إرجاع الاستجابة كنتيجة للأسلوبInsertSessionAsync
.return await _container.CreateItemAsync<Session>( item: session, partitionKey: partitionKey );
InsertMessageAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task<Message> InsertMessageAsync(Message message) { }
PartitionKey
إنشاء متغير باستخدامsession.SessionId
كقيمة لمفتاح القسم.PartitionKey partitionKey = new(message.SessionId);
قم بإنشاء متغير رسالة جديد باسم
newMessage
معTimestamp
خاصية محدثة إلى الطابع الزمني الحالي UTC.Message newMessage = message with { TimeStamp = DateTime.UtcNow };
CreateItemAsync
استدعاء تمرير في كل من متغيرات مفتاح التقسيم والرسالة الجديدة. إرجاع الاستجابة كنتيجة لInsertMessageAsync
.return await _container.CreateItemAsync<Message>( item: newMessage, partitionKey: partitionKey );
احفظ ملف Services/CosmosDbService.cs.
استرداد جلسات عمل أو رسائل متعددة
هناك حالتان رئيسيتان للاستخدام حيث يحتاج التطبيق إلى استرداد عناصر متعددة من حاويتنا. أولا، يسترد التطبيق جميع جلسات العمل للمستخدم الحالي عن طريق تصفية العناصر إلى العناصر حيث type = Session
. ثانيا، يسترد التطبيق جميع الرسائل لجلسة عمل عن طريق تنفيذ عامل تصفية مشابه حيث type = Session & sessionId = <current-session-id>
. تنفيذ كلا الاستعلامين هنا باستخدام .NET SDK ومكرر الخلاصة.
GetSessionsAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task<List<Session>> GetSessionsAsync() { }
إنشاء متغير جديد يسمى
query
من النوعQueryDefinition
باستخدام استعلامSELECT DISTINCT * FROM c WHERE c.type = @type
SQL . استخدم الأسلوب بطلاقةWithParameter
لتعيين اسمSession
الفئة كقيمة للمعلمة .QueryDefinition query = new QueryDefinition("SELECT DISTINCT * FROM c WHERE c.type = @type") .WithParameter("@type", nameof(Session));
استدعاء الأسلوب العام
GetItemQueryIterator<>
على المتغير الذي_container
يمر في النوعSession
العام والمتغيرquery
كمعلمة. تخزين النتيجة في متغير من النوعFeedIterator<Session>
المسمىresponse
.FeedIterator<Session> response = _container.GetItemQueryIterator<Session>(query);
إنشاء متغير قائمة عام جديد باسم
output
.List<Session> output = new();
إنشاء تكرار حلقي لفترة زمنية يتم تشغيله حتى
response.HasMoreResults
لا يعود صحيحا.while (response.HasMoreResults) { }
إشعار
سيؤدي استخدام التكرار الحلقي في حين هنا إلى تكرار التكرار الحلقي بشكل فعال عبر جميع صفحات الاستجابة حتى لا تبقى صفحات.
ضمن التكرار الحلقي while، احصل بشكل غير متزامن على الصفحة التالية من النتائج عن طريق استدعاء
ReadNextAsync
علىresponse
المتغير ثم أضف هذه النتائج إلى متغير القائمة المسمىoutput
.FeedResponse<Session> results = await response.ReadNextAsync(); output.AddRange(results);
خارج التكرار الحلقي while، قم بإرجاع
output
المتغير بقائمة جلسات العمل كنتيجة للأسلوبGetSessionsAsync
.return output;
GetSessionMessagesAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task<List<Message>> GetSessionMessagesAsync(string sessionId) { }
query
إنشاء متغير من النوعQueryDefinition
. استخدم استعلامSELECT * FROM c WHERE c.sessionId = @sessionId AND c.type = @type
SQL . استخدم الأسلوب بطلاقةWithParameter
لتعيين المعلمة@sessionId
إلى معرف جلسة العمل الذي تم تمريره كمعلمة، والمعلمة@type
إلى اسمMessage
الفئة.QueryDefinition query = new QueryDefinition("SELECT * FROM c WHERE c.sessionId = @sessionId AND c.type = @type") .WithParameter("@sessionId", sessionId) .WithParameter("@type", nameof(Message));
FeedIterator<Message>
إنشاء باستخدامquery
المتغير والأسلوبGetItemQueryIterator<>
.FeedIterator<Message> response = _container.GetItemQueryIterator<Message>(query);
استخدم حلقة while للتكرار عبر جميع صفحات النتائج وتخزين النتائج في متغير واحد
List<Message>
يسمىoutput
.List<Message> output = new(); while (response.HasMoreResults) { FeedResponse<Message> results = await response.ReadNextAsync(); output.AddRange(results); }
output
إرجاع المتغير كنتيجة للأسلوبGetSessionMessagesAsync
.return output;
احفظ ملف Services/CosmosDbService.cs.
تحديث جلسة عمل أو رسالة واحدة أو أكثر
هناك سيناريوهات عندما تتطلب جلسة عمل واحدة تحديثا أو تتطلب أكثر من رسالة تحديثا. بالنسبة للسيناريو الأول، استخدم ReplaceItemAsync
أسلوب SDK لاستبدال عنصر موجود بإصدار معدل. بالنسبة للسيناريو الثاني، استخدم إمكانية دفعة المعاملات ل SDK لتعديل رسائل متعددة في دفعة واحدة.
UpdateSessionAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task<Session> UpdateSessionAsync(Session session) { }
PartitionKey
إنشاء متغير باستخدامsession.SessionId
كقيمة لمفتاح القسم.PartitionKey partitionKey = new(session.SessionId);
ReplaceItemAsync
استدعاء التمرير في المعرف الفريد للرسالة الجديدة ومفتاح القسم. إرجاع الاستجابة كنتيجة لUpdateSessionAsync
.return await _container.ReplaceItemAsync( item: session, id: session.Id, partitionKey: partitionKey );
UpsertSessionBatchAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task UpsertSessionBatchAsync(params dynamic[] messages) { }
تحقق من أن جميع الرسائل تحتوي على معرف جلسة عمل واحد (
SessionId
) باستخدام استعلام متكامل اللغة (LINQ). إذا كانت أي من الرسائل تحتوي على قيمة مختلفة، فقم بطرحArgumentException
.if (messages.Select(m => m.SessionId).Distinct().Count() > 1) { throw new ArgumentException("All items must have the same partition key."); }
إنشاء متغير جديد
PartitionKey
باستخدامSessionId
خاصية للرسالة الأولى.PartitionKey partitionKey = new(messages.First().SessionId);
إشعار
تذكر، يمكنك افتراض أن جميع الرسائل لها نفس معرف جلسة العمل إذا كان التطبيق قد انتقل إلى هذه النقطة في التعليمات البرمجية للأسلوب.
إنشاء متغير جديد يسمى
batch
من النوعTransactionalBatch
عن طريق استدعاءCreateTransactionalBatch
أسلوب_container
المتغير. استخدم متغير مفتاح القسم الحالي لعمليات الدفعة.TransactionalBatch batch = _container.CreateTransactionalBatch(partitionKey);
هام
تذكر أن جميع المعاملات داخل هذه الدفعة يجب أن تكون في نفس القسم المنطقي.
التكرار فوق كل رسالة في
messages
الصفيف باستخدام حلقة foreach.foreach (var message in messages) { }
ضمن حلقة foreach، أضف كل رسالة كلعملية upsert إلى الدفعة.
batch.UpsertItem( item: message );
إشعار
يخبر Upsert Azure Cosmos DB بتحديد ما إذا كان يجب استبدال عنصر أو تحديثه، من جانب الخادم. سيقوم Azure Cosmos DB بإجراء هذا التحديد باستخدام
id
و مفتاح القسم لكل عنصر.خارج حلقة foreach، استدع
ExecuteAsync
أسلوب الدفعة بشكل غير متزامن لتنفيذ جميع العمليات داخل الدفعة.await batch.ExecuteAsync();
احفظ ملف Services/CosmosDbService.cs.
إزالة جلسة عمل وكافة الرسائل ذات الصلة
وأخيرا، اجمع بين وظيفة الاستعلام ووظيفة دفعة المعاملات لإزالة عناصر متعددة. في هذا المثال، احصل على عنصر جلسة العمل وكافة الرسائل ذات الصلة عن طريق الاستعلام عن جميع العناصر باستخدام معرف جلسة عمل معين بغض النظر عن النوع. ثم قم بإنشاء دفعة معاملات لحذف جميع العناصر المتطابقة كمعاملة واحدة.
DeleteSessionAndMessagesAsync
ضمن الأسلوب ، قم بإزالة أي رمز نائب موجود.public async Task DeleteSessionAndMessagesAsync(string sessionId) { }
إنشاء متغير يسمى
partitionKey
من النوعPartitionKey
باستخدام قيمة السلسلة التيsesionId
تم تمريرها كمعلمة إلى هذا الأسلوب.PartitionKey partitionKey = new(sessionId);
باستخدام نفس
sessionId
معلمة الأسلوب، قم بإنشاء كائنQueryDefinition
يعثر على كافة العناصر التي تطابق معرف جلسة العمل. استخدم معلمة استعلام لsessionId
وتأكد من عدم تصفية الاستعلام على نوع العنصر.QueryDefinition query = new QueryDefinition("SELECT VALUE c.id FROM c WHERE c.sessionId = @sessionId") .WithParameter("@sessionId", sessionId);
إشعار
إذا قمت بتطبيق عامل
type
تصفية في هذا الاستعلام، فقد تفوت عن غير قصد الرسائل أو الجلسات ذات الصلة التي يجب إزالتها بشكل مجمع كجزء من هذه العملية.إنشاء جديد
FeedIterator<string>
باستخدامGetItemQueryIterator
والاستعلام الذي أنشأته.FeedIterator<string> response = _container.GetItemQueryIterator<string>(query);
إنشاء مسمى
TransactionalBatch
batch
باستخدامCreateTransactionalBatch
ومتغير مفتاح القسم.TransactionalBatch batch = _container.CreateTransactionalBatch(partitionKey);
إنشاء تكرار حلقي للتكرار عبر جميع صفحات النتائج. ضمن التكرار الحلقي while، احصل على الصفحة التالية من النتائج واستخدم حلقة foreach للتكرار من خلال جميع معرفات العناصر لكل صفحة. ضمن حلقة foreach، أضف عملية دفعة لحذف العنصر باستخدام
batch.DeleteItem
.while (response.HasMoreResults) { FeedResponse<string> results = await response.ReadNextAsync(); foreach (var itemId in results) { batch.DeleteItem( id: itemId ); } }
بعد التكرار الحلقي أثناء، قم بتنفيذ الدفعة باستخدام
batch.ExecuteAsync
.await batch.ExecuteAsync();
احفظ ملف Services/CosmosDbService.cs.
راجع عملك
الآن التطبيق الخاص بك لديه تنفيذ كامل من Azure OpenAI وAzure Cosmos DB. يمكنك اختبار التطبيق من طرف إلى طرف عن طريق تصحيح أخطاء الحل.
افتح محطة طرفية جديدة.
ابدأ تشغيل التطبيق مع تمكين عمليات إعادة التحميل السريع باستخدام
dotnet watch
.dotnet watch run --non-interactive
يقوم Visual Studio Code بتشغيل المتصفح البسيط داخل الأداة مرة أخرى مع تشغيل تطبيق الويب. في تطبيق الويب، أنشئ جلسة دردشة جديدة واطرح سؤالا على مساعد الذكاء الاصطناعي. ثم أغلق تطبيق الويب قيد التشغيل.
أغلق المحطة الطرفية. الآن، افتح محطة طرفية جديدة.
ابدأ تشغيل التطبيق مرة أخرى مع تمكين عمليات إعادة التحميل الساخنة باستخدام
dotnet watch
.dotnet watch run --non-interactive
يقوم Visual Studio Code بتشغيل المتصفح البسيط داخل الأداة مرة أخرى مع تشغيل تطبيق الويب. لهذا التكرار، لاحظ أن جلسات الدردشة الخاصة بك مستمرة بين جلسات تصحيح الأخطاء.
أغلق المحطة الطرفية.