using candy_shop_ai.Model; using MongoDB.Bson; using MongoDB.Driver; using System.Numerics; namespace candy_shop_ai.Repository { public class CandiesRepo : ICandiesRepo { private IMongoCollection _candiesCollection; private readonly ILogger _logger; private string _aiIdxName = "gen-ai-idx"; public CandiesRepo(IMongoClient mongoClient, MongoUrl mongoUrl, ILogger logger) { _logger = logger; var db = mongoClient.GetDatabase(mongoUrl?.DatabaseName); var collectionName = "Candies"; _aiIdxName = "gen-ai-idx"; _candiesCollection = db.GetCollection(collectionName); CreateIndex(_aiIdxName); _logger = logger; } private void CreateIndex(string indexName) { var indexDef = new BsonDocument { { "mappings", new BsonDocument { {"name",indexName }, {"dynamic", true }, {"fields", new BsonDocument { {"embeddings", new BsonDocument { {"type","knnVector" }, {"dimensions",1}, {"similarity","cosine" } } } } } } } }; var searchIndexModel = new CreateSearchIndexModel(indexName, indexDef); _candiesCollection.SearchIndexes.CreateOne(searchIndexModel); } public async Task> SeedCandiesAsync(List candies) { await _candiesCollection.InsertManyAsync(candies); return candies; } public async Task GetCandiesByIdAsync(string candyId) { return (await _candiesCollection.FindAsync(fc => fc.Id == candyId)).FirstOrDefault(); } public async Task> GetAllCandies() { return await _candiesCollection.AsQueryable().ToListAsync(); } public async TaskGetRecordCount() { return await _candiesCollection.CountDocumentsAsync(Builders.Filter.Empty); } public async Task SearchCandiesGenAIAsync(double[] userTextEmbeddings) { var options = new VectorSearchOptions() { IndexName = "_aiIdxName", NumberOfCandidates = 5 }; var results = await _candiesCollection.Aggregate() .VectorSearch(candy => candy.Embeddings, userTextEmbeddings, 1, options) .ToListAsync(); return results?[0]; } public async Task UpdateCandyEmbeddingsAsync(string candyId, double[] embedding) { var filter = Builders.Filter.Eq(nameof(Candy.Id), candyId); var update = Builders.Update.Set(nameof(Candy.Embeddings), embedding); var modifiedCount = await _candiesCollection.UpdateOneAsync(filter, update); return modifiedCount.ModifiedCount > 0; } public async Task DeleteCandiesAsync(string candyId) { var filter = Builders.Filter.Eq(nameof(Candy.Id), candyId); var deletedResult = await _candiesCollection.DeleteOneAsync(filter); return deletedResult.DeletedCount > 0; } public async TaskDeleteAllAsync() { var deleteResult=await _candiesCollection.DeleteManyAsync(Builders.Filter.Empty); return deleteResult.DeletedCount>=0; } } }