Skip to content

Commit 7a11bac

Browse files
committed
CSHARP-1373, CSHARP-1367: added $stdDevPop and $stdDevSamp expression and group support.
1 parent 3661126 commit 7a11bac

File tree

17 files changed

+2328
-3
lines changed

17 files changed

+2328
-3
lines changed

Docs/reference/content/reference/driver/expressions.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,24 @@ p => p.FavoriteNumbers.Skip(3).Take(2)
803803
{ $slice: ['$FavoriteNumbers', 3, 2] }
804804
```
805805

806+
#### $stdDevPop
807+
808+
```csharp
809+
p => p.FavoriteNumbers.StandardDeviationPopulation()
810+
```
811+
```json
812+
{ $stdDevPop: '$FavoriteNumbers' }
813+
```
814+
815+
#### $stdDevSamp
816+
817+
```csharp
818+
p => p.FavoriteNumbers.StandardDeviationSample()
819+
```
820+
```json
821+
{ $stdDevPop: '$FavoriteNumbers' }
822+
```
823+
806824
#### $sum
807825

808826
```csharp

src/MongoDB.Driver.Tests/Linq/MongoQueryableTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,70 @@ public void Skip()
906906
"{ $skip: 10 }");
907907
}
908908

909+
[Test]
910+
public void StandardDeviationPopulation()
911+
{
912+
var result = CreateQuery().Select(x => x.C.E.F).StandardDeviationPopulation();
913+
914+
result.Should().Be(50);
915+
}
916+
917+
[Test]
918+
public void StandardDeviationPopulation_with_selector()
919+
{
920+
var result = CreateQuery().StandardDeviationPopulation(x => x.C.E.F);
921+
922+
result.Should().Be(50);
923+
}
924+
925+
[Test]
926+
public async Task StandardDeviationPopulationAsync()
927+
{
928+
var result = await CreateQuery().Select(x => x.C.E.F).StandardDeviationPopulationAsync();
929+
930+
result.Should().Be(50);
931+
}
932+
933+
[Test]
934+
public async Task StandardDeviationPopulationAsync_with_selector()
935+
{
936+
var result = await CreateQuery().StandardDeviationPopulationAsync(x => x.C.E.F);
937+
938+
result.Should().Be(50);
939+
}
940+
941+
[Test]
942+
public void StandardDeviationSample()
943+
{
944+
var result = CreateQuery().Select(x => x.C.E.F).StandardDeviationSample();
945+
946+
result.Should().BeApproximately(70.7106781186548, .0001);
947+
}
948+
949+
[Test]
950+
public void StandardDeviationSample_with_selector()
951+
{
952+
var result = CreateQuery().StandardDeviationSample(x => x.C.E.F);
953+
954+
result.Should().BeApproximately(70.7106781186548, .0001);
955+
}
956+
957+
[Test]
958+
public async Task StandardDeviationSampleAsync()
959+
{
960+
var result = await CreateQuery().Select(x => x.C.E.F).StandardDeviationSampleAsync();
961+
962+
result.Should().BeApproximately(70.7106781186548, .0001);
963+
}
964+
965+
[Test]
966+
public async Task StandardDeviationSampleAsync_with_selector()
967+
{
968+
var result = await CreateQuery().StandardDeviationSampleAsync(x => x.C.E.F);
969+
970+
result.Should().BeApproximately(70.7106781186548, .0001);
971+
}
972+
909973
[Test]
910974
public void Sum()
911975
{

src/MongoDB.Driver.Tests/Linq/Translators/AggregateGroupTranslatorTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
using MongoDB.Bson;
2323
using MongoDB.Bson.Serialization;
2424
using MongoDB.Driver;
25+
using MongoDB.Driver.Core;
26+
using MongoDB.Driver.Linq;
2527
using MongoDB.Driver.Linq.Translators;
2628
using NUnit.Framework;
2729

@@ -260,6 +262,50 @@ public async Task Should_translate_push_with_ToList()
260262
result.Value.Result.Should().Equal(111);
261263
}
262264

265+
[Test]
266+
[RequiresServer(MinimumVersion = "3.1.7")]
267+
public async Task Should_translate_stdDevPop_with_embedded_projector()
268+
{
269+
var result = await Group(x => 1, g => new { Result = g.StandardDeviationPopulation(x => x.C.E.F) });
270+
271+
result.Projection.Should().Be("{ _id: 1, Result: { \"$stdDevPop\": \"$C.E.F\" } }");
272+
273+
result.Value.Result.Should().Be(50);
274+
}
275+
276+
[Test]
277+
[RequiresServer(MinimumVersion = "3.1.7")]
278+
public async Task Should_translate_stdDevPop_with_selected_projector()
279+
{
280+
var result = await Group(x => 1, g => new { Result = g.Select(x => x.C.E.F).StandardDeviationPopulation() });
281+
282+
result.Projection.Should().Be("{ _id: 1, Result: { \"$stdDevPop\": \"$C.E.F\" } }");
283+
284+
result.Value.Result.Should().Be(50);
285+
}
286+
287+
[Test]
288+
[RequiresServer(MinimumVersion = "3.1.7")]
289+
public async Task Should_translate_stdDevSamp_with_embedded_projector()
290+
{
291+
var result = await Group(x => 1, g => new { Result = g.StandardDeviationSample(x => x.C.E.F) });
292+
293+
result.Projection.Should().Be("{ _id: 1, Result: { \"$stdDevSamp\": \"$C.E.F\" } }");
294+
295+
result.Value.Result.Should().BeApproximately(70.7106781156545, .0001);
296+
}
297+
298+
[Test]
299+
[RequiresServer(MinimumVersion = "3.1.7")]
300+
public async Task Should_translate_stdDevSamp_with_selected_projector()
301+
{
302+
var result = await Group(x => 1, g => new { Result = g.Select(x => x.C.E.F).StandardDeviationSample() });
303+
304+
result.Projection.Should().Be("{ _id: 1, Result: { \"$stdDevSamp\": \"$C.E.F\" } }");
305+
306+
result.Value.Result.Should().BeApproximately(70.7106781156545, .0001);
307+
}
308+
263309
[Test]
264310
public async Task Should_translate_sum_with_embedded_projector()
265311
{

src/MongoDB.Driver.Tests/Linq/Translators/AggregateProjectTranslatorTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using MongoDB.Bson;
2323
using MongoDB.Bson.Serialization;
2424
using MongoDB.Driver.Core;
25+
using MongoDB.Driver.Linq;
2526
using MongoDB.Driver.Linq.Translators;
2627
using NUnit.Framework;
2728

@@ -866,6 +867,50 @@ public async Task Should_translate_select_with_an_anonymous_type_then_where_to_m
866867
result.Value.Result.Single().F.Should().Be(33);
867868
}
868869

870+
[Test]
871+
[RequiresServer(MinimumVersion = "3.1.7")]
872+
public async Task Should_translate_stdDevPop()
873+
{
874+
var result = await Project(x => new { Result = x.M.StandardDeviationPopulation() });
875+
876+
result.Projection.Should().Be("{ Result: { \"$stdDevPop\": \"$M\" }, _id: 0 }");
877+
878+
result.Value.Result.Should().BeApproximately(1.247219128924647, .0001);
879+
}
880+
881+
[Test]
882+
[RequiresServer(MinimumVersion = "3.1.7")]
883+
public async Task Should_translate_stdDevPop_with_selector()
884+
{
885+
var result = await Project(x => new { Result = x.G.StandardDeviationPopulation(g => g.E.F) });
886+
887+
result.Projection.Should().Be("{ Result: { \"$stdDevPop\": \"$G.E.F\" }, _id: 0 }");
888+
889+
result.Value.Result.Should().Be(11);
890+
}
891+
892+
[Test]
893+
[RequiresServer(MinimumVersion = "3.1.7")]
894+
public async Task Should_translate_stdDevSamp()
895+
{
896+
var result = await Project(x => new { Result = x.M.StandardDeviationSample() });
897+
898+
result.Projection.Should().Be("{ Result: { \"$stdDevSamp\": \"$M\" }, _id: 0 }");
899+
900+
result.Value.Result.Should().BeApproximately(1.5275252316519468, .0001);
901+
}
902+
903+
[Test]
904+
[RequiresServer(MinimumVersion = "3.1.7")]
905+
public async Task Should_translate_stdDevSamp_with_selector()
906+
{
907+
var result = await Project(x => new { Result = x.G.StandardDeviationSample(g => g.E.F) });
908+
909+
result.Projection.Should().Be("{ Result: { \"$stdDevSamp\": \"$G.E.F\" }, _id: 0 }");
910+
911+
result.Value.Result.Should().BeApproximately(15.556349186104045, .0001);
912+
}
913+
869914
[Test]
870915
public async Task Should_translate_string_equals()
871916
{

src/MongoDB.Driver/Linq/Expressions/AccumulatorType.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ internal enum AccumulatorType
2424
Min,
2525
Max,
2626
Push,
27-
Sum
27+
StandardDeviationPopulation,
28+
StandardDeviationSample,
29+
Sum,
2830
}
2931
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2015 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Linq.Expressions;
18+
using MongoDB.Driver.Core.Misc;
19+
20+
namespace MongoDB.Driver.Linq.Expressions.ResultOperators
21+
{
22+
internal sealed class StandardDeviationResultOperator : ResultOperator, IResultTransformer
23+
{
24+
private readonly bool _isSample;
25+
private readonly Type _type;
26+
27+
public StandardDeviationResultOperator(Type type, bool isSample)
28+
{
29+
_type = Ensure.IsNotNull(type, nameof(type));
30+
_isSample = isSample;
31+
}
32+
33+
public bool IsSample
34+
{
35+
get { return _isSample; }
36+
}
37+
38+
public override string Name
39+
{
40+
get { return "StandardDeviation" + (_isSample ? "Sample" : "Population"); }
41+
}
42+
43+
public override Type Type
44+
{
45+
get { return _type; }
46+
}
47+
48+
public LambdaExpression CreateAggregator(Type sourceType)
49+
{
50+
return ResultTransformerHelper.CreateAggregator("Single", sourceType);
51+
}
52+
53+
public LambdaExpression CreateAsyncAggregator(Type sourceType)
54+
{
55+
return ResultTransformerHelper.CreateAsyncAggregator("SingleAsync", sourceType);
56+
}
57+
}
58+
}

src/MongoDB.Driver/Linq/MethodHelper.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public static IEnumerable<MethodInfo> GetEnumerableAndQueryableMethodDefinitions
6868
return typeof(Enumerable)
6969
.GetMethods()
7070
.Concat(typeof(Queryable).GetMethods())
71+
.Concat(typeof(MongoEnumerable).GetMethods())
72+
.Concat(typeof(MongoQueryable).GetMethods())
7173
.Where(x => x.Name == name)
7274
.Select(x => GetMethodDefinition(x));
7375
}

0 commit comments

Comments
 (0)