public void IncludeTimeSeriesAndUpdateExistingRangeInCache_Typed() { using (var store = GetDocumentStore()) { var baseline = RavenTestHelper.UtcToday; using (var session = store.OpenSession()) { session.Store(new User { Name = "Oren" }, "users/ayende"); session.SaveChanges(); } using (var session = store.OpenSession()) { var tsf = session.TimeSeriesFor <HeartRateMeasure>("users/ayende"); for (int i = 0; i < 360; i++) { var typedMeasure = new HeartRateMeasure { HeartRate = 6 }; tsf.Append(baseline.AddSeconds(i * 10), typedMeasure, "watches/fitbit"); } session.SaveChanges(); } using (var session = store.OpenSession()) { var vals = session.TimeSeriesFor <HeartRateMeasure>("users/ayende") .Get(baseline.AddMinutes(2), baseline.AddMinutes(10)) .ToList(); Assert.Equal(1, session.Advanced.NumberOfRequests); Assert.Equal(49, vals.Count); Assert.Equal(baseline.AddMinutes(2), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(10), vals[48].Timestamp, RavenTestHelper.DateTimeComparer.Instance); session.TimeSeriesFor <HeartRateMeasure>("users/ayende") .Append(baseline.AddMinutes(3).AddSeconds(3), new HeartRateMeasure { HeartRate = 6 }, "watches/fitbit"); session.SaveChanges(); Assert.Equal(2, session.Advanced.NumberOfRequests); var user = session.Load <User>( "users/ayende", i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(3), baseline.AddMinutes(5))); Assert.Equal(3, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>("users/ayende") .Get(baseline.AddMinutes(3), baseline.AddMinutes(5)) .ToList(); Assert.Equal(3, session.Advanced.NumberOfRequests); Assert.Equal(14, vals.Count); Assert.Equal(baseline.AddMinutes(3), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(3).AddSeconds(3), vals[1].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(5), vals[13].Timestamp, RavenTestHelper.DateTimeComparer.Instance); } } }
public void CanQueryTimeSeriesAggregation_NoSelectOrGroupBy() { using (var store = GetDocumentStore()) { var baseline = RavenTestHelper.UtcToday; using (var session = store.OpenSession()) { for (int i = 1; i <= 3; i++) { var id = $"people/{i}"; session.Store(new User { Name = "Oren", Age = i * 30 }, id); var tsf = session.TimeSeriesFor <HeartRateMeasure>(id); var m = new HeartRateMeasure { HeartRate = 59d, }; tsf.Append(baseline.AddMinutes(61), m, "watches/fitbit"); m.HeartRate = 79d; tsf.Append(baseline.AddMinutes(62), m, "watches/fitbit"); m.HeartRate = 69d; tsf.Append(baseline.AddMinutes(63), m, "watches/apple"); m.HeartRate = 159d; tsf.Append(baseline.AddMonths(1).AddMinutes(61), m, "watches/fitbit"); m.HeartRate = 179d; tsf.Append(baseline.AddMonths(1).AddMinutes(62), m, "watches/apple"); m.HeartRate = 169d; tsf.Append(baseline.AddMonths(1).AddMinutes(63), m, "watches/fitbit"); } session.SaveChanges(); } using (var session = store.OpenSession()) { var query = session.Advanced.RawQuery <TimeSeriesRawResult <HeartRateMeasure> >(@" declare timeseries out(x) { from x.HeartRateMeasures between $start and $end } from Users as doc where doc.Age > 49 select out(doc) ") .AddParameter("start", baseline.EnsureUtc()) .AddParameter("end", baseline.AddMonths(2).EnsureUtc()); var result = query.ToList(); Assert.Equal(2, result.Count); for (int i = 0; i < 2; i++) { var agg = result[i]; Assert.Equal(6, agg.Results.Length); var val = agg.Results[0]; Assert.Equal(1, val.Values.Length); Assert.Equal(59, val.Value.HeartRate); Assert.Equal("watches/fitbit", val.Tag); Assert.Equal(baseline.AddMinutes(61), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); val = agg.Results[1]; Assert.Equal(1, val.Values.Length); Assert.Equal(79, val.Value.HeartRate); Assert.Equal("watches/fitbit", val.Tag); Assert.Equal(baseline.AddMinutes(62), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); val = agg.Results[2]; Assert.Equal(1, val.Values.Length); Assert.Equal(69, val.Value.HeartRate); Assert.Equal("watches/apple", val.Tag); Assert.Equal(baseline.AddMinutes(63), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); val = agg.Results[3]; Assert.Equal(1, val.Values.Length); Assert.Equal(159, val.Value.HeartRate); Assert.Equal("watches/fitbit", val.Tag); Assert.Equal(baseline.AddMonths(1).AddMinutes(61), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); val = agg.Results[4]; Assert.Equal(1, val.Values.Length); Assert.Equal(179, val.Value.HeartRate); Assert.Equal("watches/apple", val.Tag); Assert.Equal(baseline.AddMonths(1).AddMinutes(62), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); val = agg.Results[5]; Assert.Equal(1, val.Values.Length); Assert.Equal(169, val.Value.HeartRate); Assert.Equal("watches/fitbit", val.Tag); Assert.Equal(baseline.AddMonths(1).AddMinutes(63), val.Timestamp, RavenTestHelper.DateTimeComparer.Instance); } } } }
public void IncludeTimeSeriesAndMergeWithExistingRangesInCache_Typed() { using (var store = GetDocumentStore()) { var baseline = RavenTestHelper.UtcToday; var documentId = "users/ayende"; using (var session = store.OpenSession()) { session.Store(new User { Name = "Oren" }, documentId); session.SaveChanges(); } using (var session = store.OpenSession()) { var tsf = session.TimeSeriesFor <HeartRateMeasure>(documentId); for (int i = 0; i < 360; i++) { var typedMeasure = new HeartRateMeasure { HeartRate = 6 }; tsf.Append(baseline.AddSeconds(i * 10), typedMeasure, "watches/fitbit"); } session.SaveChanges(); } using (var session = store.OpenSession()) { var vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(2), baseline.AddMinutes(10)) .ToList(); Assert.Equal(1, session.Advanced.NumberOfRequests); Assert.Equal(49, vals.Count); Assert.Equal(baseline.AddMinutes(2), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(10), vals[48].Timestamp, RavenTestHelper.DateTimeComparer.Instance); var user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(40), baseline.AddMinutes(50))); Assert.Equal(2, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(40), baseline.AddMinutes(50)) .ToList(); Assert.Equal(2, session.Advanced.NumberOfRequests); Assert.Equal(61, vals.Count); Assert.Equal(baseline.AddMinutes(40), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), vals[60].Timestamp, RavenTestHelper.DateTimeComparer.Instance); var sessionOperations = (InMemoryDocumentSessionOperations)session; Assert.True(sessionOperations.TimeSeriesByDocId.TryGetValue(documentId, out var cache)); Assert.True(cache.TryGetValue("HeartRateMeasures", out var ranges)); Assert.Equal(2, ranges.Count); Assert.Equal(baseline.AddMinutes(2), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(10), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(40), ranges[1].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[1].To, RavenTestHelper.DateTimeComparer.Instance); // we intentionally evict just the document (without it's TS data), // so that Load request will go to server sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get [0, 2] and merge it into existing [2, 10] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline, baseline.AddMinutes(2))); Assert.Equal(3, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline, baseline.AddMinutes(2)) .ToList(); Assert.Equal(3, session.Advanced.NumberOfRequests); Assert.Equal(13, vals.Count); Assert.Equal(baseline, vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(2), vals[12].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(2, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(10), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(40), ranges[1].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[1].To, RavenTestHelper.DateTimeComparer.Instance); // evict just the document sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get [10, 16] and merge it into existing [0, 10] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(10), baseline.AddMinutes(16))); Assert.Equal(4, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(10), baseline.AddMinutes(16)) .ToList(); Assert.Equal(4, session.Advanced.NumberOfRequests); Assert.Equal(37, vals.Count); Assert.Equal(baseline.AddMinutes(10), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(16), vals[36].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(2, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(16), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(40), ranges[1].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[1].To, RavenTestHelper.DateTimeComparer.Instance); // evict just the document sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get range [17, 19] // and add it to cache in between [10, 16] and [40, 50] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(17), baseline.AddMinutes(19))); Assert.Equal(5, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(17), baseline.AddMinutes(19)) .ToList(); Assert.Equal(5, session.Advanced.NumberOfRequests); Assert.Equal(13, vals.Count); Assert.Equal(baseline.AddMinutes(17), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(19), vals[12].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(3, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(16), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(17), ranges[1].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(19), ranges[1].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(40), ranges[2].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[2].To, RavenTestHelper.DateTimeComparer.Instance); // evict just the document sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get range [19, 40] // and merge the result with existing ranges [17, 19] and [40, 50] // into single range [17, 50] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(18), baseline.AddMinutes(48))); Assert.Equal(6, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(18), baseline.AddMinutes(48)) .ToList(); Assert.Equal(6, session.Advanced.NumberOfRequests); Assert.Equal(181, vals.Count); Assert.Equal(baseline.AddMinutes(18), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(48), vals[180].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(2, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(16), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(17), ranges[1].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[1].To, RavenTestHelper.DateTimeComparer.Instance); // evict just the document sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get range [12, 22] // and merge the result with existing ranges [0, 16] and [17, 50] // into single range [0, 50] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", baseline.AddMinutes(12), baseline.AddMinutes(22))); Assert.Equal(7, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(12), baseline.AddMinutes(22)) .ToList(); Assert.Equal(7, session.Advanced.NumberOfRequests); Assert.Equal(61, vals.Count); Assert.Equal(baseline.AddMinutes(12), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(22), vals[60].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(1, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(50), ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); // evict just the document sessionOperations.DocumentsByEntity.Evict(user); sessionOperations.DocumentsById.Remove(documentId); // should go to server to get range [50, ∞] // and merge the result with existing range [0, 50] into single range [0, ∞] user = session.Load <User>( documentId, i => i.IncludeTimeSeries("HeartRateMeasures", TimeSeriesRangeType.Last, TimeValue.FromMinutes(10))); Assert.Equal(8, session.Advanced.NumberOfRequests); // should not go to server vals = session.TimeSeriesFor <HeartRateMeasure>(documentId) .Get(baseline.AddMinutes(50)) .ToList(); Assert.Equal(8, session.Advanced.NumberOfRequests); Assert.Equal(60, vals.Count); Assert.Equal(baseline.AddMinutes(50), vals[0].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(59).AddSeconds(50), vals[59].Timestamp, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(1, ranges.Count); Assert.Equal(baseline.AddMinutes(0), ranges[0].From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(DateTime.MaxValue, ranges[0].To, RavenTestHelper.DateTimeComparer.Instance); } } }
public unsafe void CanQueryTimeSeriesAggregation_DeclareSyntax_AllDocsQuery() { using (var store = GetDocumentStore()) { var baseline = RavenTestHelper.UtcToday; using (var session = store.OpenSession()) { session.Store(new { Name = "Oren" }, "users/ayende"); var tsf = session.TimeSeriesFor <HeartRateMeasure>("users/ayende"); var tag = "watches/fitbit"; var m = new HeartRateMeasure { HeartRate = 59d, }; tsf.Append(baseline.AddMinutes(61), m, tag); m.HeartRate = 79d; tsf.Append(baseline.AddMinutes(62), m, tag); m.HeartRate = 69d; tsf.Append(baseline.AddMinutes(63), m, tag); session.SaveChanges(); } using (var session = store.OpenSession()) { var query = session.Advanced.RawQuery <TimeSeriesAggregationResult <HeartRateMeasure> >(@" declare timeseries out(u) { from u.HeartRateMeasures between $start and $end group by 1h select min(), max(), first(), last() } from @all_docs as u where id() == 'users/ayende' select out(u) ") .AddParameter("start", baseline.EnsureUtc()) .AddParameter("end", baseline.AddDays(1).EnsureUtc()); var agg = query.First(); if (agg.Count != 3) { var db = Databases.GetDocumentDatabaseInstanceFor(store).Result; var tss = db.DocumentsStorage.TimeSeriesStorage; using (db.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx)) using (ctx.OpenReadTransaction()) { var reader = tss.GetReader(ctx, "users/ayende", nameof(HeartRateMeasure) + "s", baseline, baseline.AddDays(1)); Assert.True(reader.Init()); Assert.NotNull(reader._tvr); var key = reader._tvr.Read(0, out var size); TimeSeriesValuesSegment.ParseTimeSeriesKey(key, size, ctx, out var docId, out var name, out DateTime baseline2); Assert.Equal("users/ayende", docId); Assert.Equal(nameof(HeartRateMeasure) + "s", name, StringComparer.InvariantCultureIgnoreCase); Assert.Equal(baseline.AddMinutes(61), baseline2, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(1, reader.SegmentsOrValues().Count()); Assert.False(query.First().Count == 3, "Query assertion failed once and passed on second try. sanity check passed"); //Assert.True(false, "Query assertion failed twice. sanity check passed"); } } Assert.Equal(3, agg.Count); Assert.Equal(1, agg.Results.Length); var val = agg.Results[0]; Assert.Equal(59, val.First.HeartRate); Assert.Equal(59, val.Min.HeartRate); Assert.Equal(69, val.Last.HeartRate); Assert.Equal(79, val.Max.HeartRate); Assert.Equal(baseline.AddMinutes(60), val.From, RavenTestHelper.DateTimeComparer.Instance); Assert.Equal(baseline.AddMinutes(120), val.To, RavenTestHelper.DateTimeComparer.Instance); } } }