Details
-
Bug
-
Resolution: Gone away
-
Unknown
-
None
-
None
-
None
-
None
Description
I'm using the C# driver version 2.14.0 and I am unable to make filtering work properly on time-series collections.
A little about my setup: I'm using .NET 6.0, Visual Studio 2022, my app is running via docker-compose where MongoDB 5.0.4 is used as a datastore via an image definition in docker-compose. It works.
I have created several collections that all have the time-series feature enabled in the same way:
var collectionName = Context.GetCollectionName<ARandomClass>(); // gets collection name from attribute defined for class |
var filter = new BsonDocument("name", collectionName); |
var collectionCursor = Database.ListCollections(new ListCollectionsOptions { Filter = filter }); |
if (collectionCursor.Any()) return; |
Database.CreateCollection(collectionName, new CreateCollectionOptions { TimeSeriesOptions = new TimeSeriesOptions(nameof(ARandomClass.Timestamp), nameof(ARandomClass.SessionId), Optional.Create<TimeSeriesGranularity?>(TimeSeriesGranularity.Minutes) |
});
|
Collection = Database.GetCollection<ARandomClass>(collectionName);
|
This works. The time series collection is created and I can verify that the collections are created as time series collection in the MongoDb container. All my other methods in my generic repositories also works as expected. I can create, delete and find single records denoted by their id, using Linq.
However, I've created some integration tests that I cannot get to work properly when using date filtering:
[Fact]
|
public async void Data_Is_Stored_As_TimeSeries_Data_And_Queryable_In_Time_Buckets() |
{
|
var ARandomClassRepository = _unitOfWorkFactory.CreateUnitOfWork().Repository<IARandomClassRepository>();
|
await ARandomClassRepository.DeleteAll();
|
var sessionIds = new [] { 111, 222, 333, 444 }; |
var timestampStart = DateTime.UtcNow;
|
var dataList = new List<ARandomClass>(); |
for (var i = 0; i < 1000; i++) |
{
|
dataList.Add(new ARandomClass |
{
|
SessionId = sessionIds[RandomNo.Between(0, sessionIds.Length)], |
Timestamp = timestampStart.AddSeconds(i),
|
ActivityLevel = RandomNo.Between(1, 100), |
Amplitude = RandomNo.Between(1, 1000), |
RrInterval = RandomNo.Between(1, 10000) |
});
|
}
|
await ARandomClassRepository.CreateMany(dataList);
|
var minuteToGetDataFrom = timestampStart.WithoutSeconds().AddMinutes(1); |
var minuteToGetDataTo = minuteToGetDataFrom.AddMinutes(1); |
var randomClasses = await ARandomClassRepository.Find(x => x.Timestamp >= minuteToGetDataFrom && x.Timestamp <= minuteToGetDataTo).ToList();
|
randomClasses.ShouldNotBeNull();
|
randomClasses.Count.ShouldBeGreaterThan(0); |
await lifetouchHeartBeatRepository.DeleteAll();
|
}
|
This does not work. I have tried a myriad of variations without success. The only way I have gotten it to work, is to create a new repository method to replace the generic Find method (which just takes a Linq expression) and practically spell out the "native MongoDB" command to get the results:
public async Task<List<ARandomClass>> GetBetweenDateRanges(DateTime startDate, DateTime endDate) |
{
|
var filterStage = new StringBuilder() |
.Append("{$match:{$and:[ {$expr: {$gte:") |
.Append("[ \"$Timestamp\",") |
.Append($"ISODate('{startDate.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}'),") |
.Append("]}}, {$expr:{ $lte:") |
.Append("[ \"$Timestamp\",") |
.Append($"ISODate('{endDate.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}')") |
.Append("]}} ]}}"); |
return await Collection.Aggregate().AppendStage<LifetouchHeartBeat>(filterStage.ToString()).ToListAsync(); |
}
|
This works!
But, it would be really nice if I could just use regular Linq expressions like I normally do to create basic filters for my data, instead of having to create specialized methods that incorporates native MongoDb commands to get it to work.