From d4ff9e030895ab9049fbd70ef82b7985d9418b0b Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 9 Jul 2024 02:34:49 -0500 Subject: [PATCH] refine state search --- .../Filters/ConversationFilter.cs | 7 +- .../Collections/AgentDocument.cs | 2 - .../Collections/ConversationDialogDocument.cs | 2 - .../Collections/ConversationStateDocument.cs | 2 - .../Collections/LlmCompletionLogDocument.cs | 2 - .../MongoDbContext.cs | 15 +++- .../MongoRepository.Conversation.cs | 86 ++++++++----------- 7 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs index c31c87cb..df31faa1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs @@ -21,11 +21,16 @@ public class ConversationFilter /// /// Check whether each key in the list is in the conversation states and its value equals to target value if not empty /// - public IEnumerable States { get; set; } = new List(); + public List States { get; set; } = new List(); } public class KeyValue { public string Key { get; set; } public string? Value { get; set; } + + public override string ToString() + { + return $"Key: {Key}, Value: {Value}"; + } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 075efc2b..4f1c5194 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -1,5 +1,3 @@ -using BotSharp.Plugin.MongoStorage.Models; - namespace BotSharp.Plugin.MongoStorage.Collections; public class AgentDocument : MongoBase diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDialogDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDialogDocument.cs index 21444c04..b71ae40c 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDialogDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDialogDocument.cs @@ -1,5 +1,3 @@ -using BotSharp.Plugin.MongoStorage.Models; - namespace BotSharp.Plugin.MongoStorage.Collections; public class ConversationDialogDocument : MongoBase diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationStateDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationStateDocument.cs index 1f8f0e90..c6068a1b 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationStateDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationStateDocument.cs @@ -1,5 +1,3 @@ -using BotSharp.Plugin.MongoStorage.Models; - namespace BotSharp.Plugin.MongoStorage.Collections; public class ConversationStateDocument : MongoBase diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/LlmCompletionLogDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/LlmCompletionLogDocument.cs index f04cb46c..f5b96c0a 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/LlmCompletionLogDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/LlmCompletionLogDocument.cs @@ -1,5 +1,3 @@ -using BotSharp.Plugin.MongoStorage.Models; - namespace BotSharp.Plugin.MongoStorage.Collections; public class LlmCompletionLogDocument : MongoBase diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs index dfbbfbaa..50647776 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs @@ -40,6 +40,19 @@ public class MongoDbContext return collection; } + private IMongoCollection CreateConversationStateIndex() + { + var collection = Database.GetCollection($"{_collectionPrefix}_ConversationStates"); + var indexes = collection.Indexes.List().ToList(); + var stateIndex = indexes.FirstOrDefault(x => x.GetElement("name").ToString().StartsWith("States.Key")); + if (stateIndex == null) + { + var indexDef = Builders.IndexKeys.Ascending("States.Key"); + collection.Indexes.CreateOne(new CreateIndexModel(indexDef)); + } + return collection; + } + private IMongoCollection CreateAgentTaskIndex() { var collection = Database.GetCollection($"{_collectionPrefix}_AgentTasks"); @@ -93,7 +106,7 @@ public class MongoDbContext => Database.GetCollection($"{_collectionPrefix}_ConversationDialogs"); public IMongoCollection ConversationStates - => Database.GetCollection($"{_collectionPrefix}_ConversationStates"); + => CreateConversationStateIndex(); public IMongoCollection ExectionLogs => Database.GetCollection($"{_collectionPrefix}_ExecutionLogs"); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index bed3a255..88163b60 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -1,5 +1,9 @@ +using Amazon.Util.Internal; using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Repositories.Filters; +using MongoDB.Bson.Serialization; +using MongoDB.Driver; +using System.Collections.Immutable; namespace BotSharp.Plugin.MongoStorage.Repository; @@ -225,91 +229,77 @@ public partial class MongoRepository public PagedItems GetConversations(ConversationFilter filter) { - var conversations = new List(); - var builder = Builders.Filter; - var filters = new List>() { builder.Empty }; + var convBuilder = Builders.Filter; + var convFilters = new List>() { convBuilder.Empty }; + // Filter conversations if (!string.IsNullOrEmpty(filter?.Id)) { - filters.Add(builder.Eq(x => x.Id, filter.Id)); + convFilters.Add(convBuilder.Eq(x => x.Id, filter.Id)); } if (!string.IsNullOrEmpty(filter?.AgentId)) { - filters.Add(builder.Eq(x => x.AgentId, filter.AgentId)); + convFilters.Add(convBuilder.Eq(x => x.AgentId, filter.AgentId)); } if (!string.IsNullOrEmpty(filter?.Status)) { - filters.Add(builder.Eq(x => x.Status, filter.Status)); + convFilters.Add(convBuilder.Eq(x => x.Status, filter.Status)); } if (!string.IsNullOrEmpty(filter?.Channel)) { - filters.Add(builder.Eq(x => x.Channel, filter.Channel)); + convFilters.Add(convBuilder.Eq(x => x.Channel, filter.Channel)); } if (!string.IsNullOrEmpty(filter?.UserId)) { - filters.Add(builder.Eq(x => x.UserId, filter.UserId)); + convFilters.Add(convBuilder.Eq(x => x.UserId, filter.UserId)); } if (!string.IsNullOrEmpty(filter?.TaskId)) { - filters.Add(builder.Eq(x => x.TaskId, filter.TaskId)); + convFilters.Add(convBuilder.Eq(x => x.TaskId, filter.TaskId)); } if (filter?.StartTime != null) { - filters.Add(builder.Gte(x => x.CreatedTime, filter.StartTime.Value)); + convFilters.Add(convBuilder.Gte(x => x.CreatedTime, filter.StartTime.Value)); } - // Check states - if (filter != null && !filter.States.IsNullOrEmpty()) + // Filter states + var stateFilters = new List>(); + if (filter != null && string.IsNullOrEmpty(filter.Id) && !filter.States.IsNullOrEmpty()) { - var targetConvIds = new List(); - foreach (var pair in filter.States) { - if (pair == null || string.IsNullOrWhiteSpace(pair.Key)) continue; - - var query = _dc.ConversationStates.AsQueryable(); - var convIds = query.AsEnumerable().Where(x => + var elementFilters = new List> { Builders.Filter.Eq(x => x.Key, pair.Key) }; + if (!string.IsNullOrEmpty(pair.Value)) { - var foundState = x.States.FirstOrDefault(s => s.Key.IsEqualTo(pair.Key)); - if (foundState == null) return false; - - if (!string.IsNullOrWhiteSpace(pair.Value)) - { - return pair.Value.IsEqualTo(foundState.Values.LastOrDefault()?.Data); - } - - return true; - }).Select(x => x.ConversationId).ToList(); - - targetConvIds = targetConvIds.Concat(convIds).Distinct().ToList(); + elementFilters.Add(Builders.Filter.Eq("Values.Data", pair.Value)); + } + stateFilters.Add(Builders.Filter.ElemMatch(x => x.States, Builders.Filter.And(elementFilters))); } - filters.Add(builder.In(x => x.Id, targetConvIds)); + var targetConvIds = _dc.ConversationStates.Find(Builders.Filter.And(stateFilters)).ToEnumerable().Select(x => x.ConversationId).Distinct().ToList(); + convFilters.Add(convBuilder.In(x => x.Id, targetConvIds)); } - var filterDef = builder.And(filters); + // Sort and paginate + var filterDef = convBuilder.And(convFilters); var sortDef = Builders.Sort.Descending(x => x.CreatedTime); var pager = filter?.Pager ?? new Pagination(); var conversationDocs = _dc.Conversations.Find(filterDef).Sort(sortDef).Skip(pager.Offset).Limit(pager.Size).ToList(); var count = _dc.Conversations.CountDocuments(filterDef); - foreach (var conv in conversationDocs) + var conversations = conversationDocs.Select(x => new Conversation { - var convId = conv.Id.ToString(); - conversations.Add(new Conversation - { - Id = convId, - AgentId = conv.AgentId.ToString(), - UserId = conv.UserId.ToString(), - TaskId = conv.TaskId, - Title = conv.Title, - Channel = conv.Channel, - Status = conv.Status, - DialogCount = conv.DialogCount, - CreatedTime = conv.CreatedTime, - UpdatedTime = conv.UpdatedTime - }); - } + Id = x.Id.ToString(), + AgentId = x.AgentId.ToString(), + UserId = x.UserId.ToString(), + TaskId = x.TaskId, + Title = x.Title, + Channel = x.Channel, + Status = x.Status, + DialogCount = x.DialogCount, + CreatedTime = x.CreatedTime, + UpdatedTime = x.UpdatedTime + }).ToList(); return new PagedItems {