Reputation: 33
I want to find documents that matches to the given year.
I am using MongoDb.Driver, and currently i need a solution with this library.
int year = 2019;
var filter = Builders<CubesDataMdb>.Filter.Eq(x => x.DateOfCreation.Year, year);
var response = await Collection.Find(filter).FirstOrDefaultAsync();
Exception says: "Unable to determine the serialization information for x => x.DateOfCreation.Year." I expect the output to be one document which year is equal to my variable, no matter what is the other part of the date
Upvotes: 1
Views: 1666
Reputation: 1313
As it is already been answered i am just going to provide an alternative approach for future reference(if anyone needs).
First the issue Unable to determine the serialization information for x => x.DateOfCreation.Year
The reason why you are getting this error is because the c#
driver is translating the given linq statement:
int year = 2019;
var filter = Builders<CubesDataMdb>.Filter.Eq(x => x.DateOfCreation.Year, year);
var response = await Collection.Find(filter).FirstOrDefaultAsync();
To mongo shell script like:
db.Collection.find({"{document}{DateOfCreation}.Year":{$eq:2019}})
So, the Mongodb c# driver is not able to map it to any field as the field {document}{DateOfCreation}.Year
does not exist in the class CubesDataMdb
or in any of the documents stored in the Database(ps a simpler explanation would be that MongoDB
does not support the linq converted syntax of field.Year
).
So, an alternative approach apart from the answer provided by John.
Aggregation:
Use a ViewModel
which have the same properties as the model CubesDataMdb
apart from an additional property
public int Year { get; set; }
Then construct a $addFields
stage to be used in the aggregation pipeline by extracting the year part from the object DateOfCreation
using $year
(by assuming the DateOfCreation
have mongo dates and not string dates) as:
BsonDocument expressionString = new BsonDocument(new List<BsonElement>() {
new BsonElement("Year", new BsonDocument(new BsonElement("$year", "$DateOfCreation"))),
});
BsonDocument addFieldsStageMongo = new BsonDocument(new BsonElement("$addFields", expressionMongo));
//adding the stage to the aggrigation pipeline
var response = await Collection
.Aggregate()
.AppendStage<BsonDocument>(addFieldsStageMongo)
.Match(m=>m.Year == year)//using the filter on the newly added field of pipeline
.FirstOrDefaultAsync();
The mongo shell equivalent query would be:
db.Collection.aggregate([
{$addFields:{
Year:{$year:"$DateOfCreation"}
}},
{
$match:{
"Year":2019
}
}
])
Upvotes: 1
Reputation: 38785
You have to search by range:
int year = 2019;
DateTime startDate = new DateTime(year, 1, 1);
DateTime endDate = new DateTime(year + 1, 1, 1);
var filter = Builders<CubesDataMdb>.Filter.Gte(x => x.DateOfCreation, startDate)
& Builders<CubesDataMdb>.Filter.Lt(x => x.DateOfCreation, endDate);
var response = await Collection.Find(filter).FirstOrDefaultAsync();
So here we're making two dates: 2019/01/01
and 2020/01/01
. Then we can search for all records whose dates are greater or equal to 2091/01/01
and less than 2020/01/01
.
Upvotes: 2