I am trying to perform a vector search on a collection and map the results into a custom object that contains only some of the properties in the collection along with the vector score. I have managed to do this with the below code but it feels untidy and I am wondering if this can all be done as a projection. It also doesn't allow me to map properties from the collection class into the custom object unless their names match.
Here is my example:
I have a collection for my Accommodation class which contains the vector. I need to do a vector search and then map the results into a list of AccommodationRecommendation.
The classes:
class Accommodation{ Guid Id { get; set; } string Name { get; set; } string Description { get; set; } string double[] { get; set; } List<AccommodationImage> AccommodationImages { get; set; }}class AccommodationImage{ string Url{ get; set; }}class AccommodationRecommendation{ HotelSlim Hotel { get; set; } double Score { get; set; }}class AccommodationLite{ Guid Id { get; set; } string Name { get; set; } string ImagerUrl { get; set; }}
This is my work so far. Note how i have to retrieve all of the images and then filter down to just one.
private async Task<List<AccommodationRecommendation>> VectorSearchInternal( System.Linq.Expressions.Expression<Func<Accommodation, object?>> field, double[] baseVector, int count, string indexName){ var output = new List<AccommodationRecommendation>(); var options = new VectorSearchOptions<Accommodation>() { IndexName = indexName, NumberOfCandidates = 10000 }; var projectionDefinition = Builders<Accommodation>.Projection .Include(a => a.Id) .Include(a => a.Name) .Include(a => a.AccommodationImages) .Meta("score", "vectorSearchScore"); var results = await Collection.Aggregate() .VectorSearch(field, baseVector, count + 1, options) .Project(projectionDefinition) .ToListAsync<BsonDocument>(); foreach (var result in results) { var accom = BsonSerializer.Deserialize<AccommodationLite>(result); var images = result["AccommodationImages"].AsBsonArray; if (images != null && images.Any()) { var image = BsonSerializer.Deserialize<Image>(images[0].AsBsonDocument); accom.ImageUrl = image.Url; } output.Add(new AccommodationRecommendation { RecommendedAccommodation = accom, Score = result["score"].AsDouble * 100 }); } return output;}