I am working on a asp.net core project with MongoDB.
I want to get a list from Database.
I tried this
public async Task<List<string>> GetRoomCodesFromHotelBooking(string transactionId)
{
return HotelBookingCollection
.Find(x => x.TransactionId == transactionId)
.Project(x => x.Hotel.Rooms.Select(y => y.Code).ToList());
}
Note : A transactionId has more than one HotelBooking
But I got this error
Cannot implicitly convert type 'MongoDB.Driver.IFindFluent<xDocument, System.Collections.Generic.List<string>>' to 'System.Collections.Generic.List<string>'. An explicit conversion exists (are you missing a cast?)
model class
public class HotelBookingDocument
{
public string Id { get; set; }
public HotelDocument Hotel { get; set; }
// removed rest
}
public class HotelDocument
{
public List<RoomDocument> Rooms { get; set; }
// removed rest
}
public class RoomDocument
{
public string Code { get; set; }
// removed rest
}
// removed rest
How can I select room code and make list them?
CodePudding user response:
Up to now, the code does not result in a List<string>
, but only in a fluent interface that needs to be executed. The following code returns a list of all codes:
public async Task<List<string>> GetRoomCodesFromHotelBooking(string transactionId)
{
// get all codes as a list of arrays
var codes = await HotelBookingCollection
.Find(x => x.TransactionId == transactionId)
.Project(x => x.Hotel.Rooms.Select(y => y.Code).ToList())
.ToListAsync();
// generate a single list of codes
return codes
.SelectMany(x => x)
.Distinct() // remove duplicates
.ToList();
}
How does it work?
- In the first step, the data are retrieved from MongoDB. Please note that - at least in theory - there might be many documents that fulfill the condition regarding the transactionId. So this returns a
List<List<string>>
- a list of list of strings. - In the next step, this
List<List<string>>
is converted into a flatList<string>
by usingSelectMany
. Afterwards, aDistinct
removes any duplicates.
Though above sample stays close to your code, you could also use an aggregation in MongoDB to achieve the same and by that, put more of the query execution onto the MongoDB cluster. The following pipeline can serve as a starting point:
[
{$match: { TransactionId: 'T123' }},
{$unwind: { path: '$Hotel', preserveNullAndEmptyArrays: false }},
{$unwind: { path: '$Hotel.Rooms', preserveNullAndEmptyArrays: false }},
{$project: { _id: 0, Code: '$Hotel.Rooms.Code' }}
]