@@ -256,6 +256,22 @@ public static ProjectionDefinition<TDocument> SearchMeta<TDocument>(
256
256
return builder . Combine ( projection , builder . SearchMeta ( field ) ) ;
257
257
}
258
258
259
+ /// <summary>
260
+ /// Combines an existing projection with an array slice projection.
261
+ /// </summary>
262
+ /// <typeparam name="TDocument">The type of the document.</typeparam>
263
+ /// <param name="projection">The projection.</param>
264
+ /// <param name="field">The field.</param>
265
+ /// <param name="limit">The limit.</param>
266
+ /// <returns>
267
+ /// A combined projection.
268
+ /// </returns>
269
+ public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , FieldDefinition < TDocument > field , int limit )
270
+ {
271
+ var builder = Builders < TDocument > . Projection ;
272
+ return builder . Combine ( projection , builder . Slice ( field , limit ) ) ;
273
+ }
274
+
259
275
/// <summary>
260
276
/// Combines an existing projection with an array slice projection.
261
277
/// </summary>
@@ -267,12 +283,28 @@ public static ProjectionDefinition<TDocument> SearchMeta<TDocument>(
267
283
/// <returns>
268
284
/// A combined projection.
269
285
/// </returns>
270
- public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , FieldDefinition < TDocument > field , int skip , int ? limit = null )
286
+ public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , FieldDefinition < TDocument > field , int skip , int limit )
271
287
{
272
288
var builder = Builders < TDocument > . Projection ;
273
289
return builder . Combine ( projection , builder . Slice ( field , skip , limit ) ) ;
274
290
}
275
291
292
+ /// <summary>
293
+ /// Combines an existing projection with an array slice projection.
294
+ /// </summary>
295
+ /// <typeparam name="TDocument">The type of the document.</typeparam>
296
+ /// <param name="projection">The projection.</param>
297
+ /// <param name="field">The field.</param>
298
+ /// <param name="limit">The limit.</param>
299
+ /// <returns>
300
+ /// A combined projection.
301
+ /// </returns>
302
+ public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , Expression < Func < TDocument , object > > field , int limit )
303
+ {
304
+ var builder = Builders < TDocument > . Projection ;
305
+ return builder . Combine ( projection , builder . Slice ( field , limit ) ) ;
306
+ }
307
+
276
308
/// <summary>
277
309
/// Combines an existing projection with an array slice projection.
278
310
/// </summary>
@@ -284,7 +316,7 @@ public static ProjectionDefinition<TDocument> Slice<TDocument>(this ProjectionDe
284
316
/// <returns>
285
317
/// A combined projection.
286
318
/// </returns>
287
- public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , Expression < Func < TDocument , object > > field , int skip , int ? limit = null )
319
+ public static ProjectionDefinition < TDocument > Slice < TDocument > ( this ProjectionDefinition < TDocument > projection , Expression < Func < TDocument , object > > field , int skip , int limit )
288
320
{
289
321
var builder = Builders < TDocument > . Projection ;
290
322
return builder . Combine ( projection , builder . Slice ( field , skip , limit ) ) ;
@@ -520,6 +552,19 @@ public ProjectionDefinition<TSource> SearchMeta(Expression<Func<TSource, object>
520
552
return SearchMeta ( new ExpressionFieldDefinition < TSource > ( field ) ) ;
521
553
}
522
554
555
+ /// <summary>
556
+ /// Creates an array slice projection.
557
+ /// </summary>
558
+ /// <param name="field">The field.</param>
559
+ /// <param name="limit">The limit.</param>
560
+ /// <returns>
561
+ /// An array slice projection.
562
+ /// </returns>
563
+ public ProjectionDefinition < TSource > Slice ( FieldDefinition < TSource > field , int limit )
564
+ {
565
+ return new SliceProjectionDefinition < TSource > ( field , limit ) ;
566
+ }
567
+
523
568
/// <summary>
524
569
/// Creates an array slice projection.
525
570
/// </summary>
@@ -529,10 +574,22 @@ public ProjectionDefinition<TSource> SearchMeta(Expression<Func<TSource, object>
529
574
/// <returns>
530
575
/// An array slice projection.
531
576
/// </returns>
532
- public ProjectionDefinition < TSource > Slice ( FieldDefinition < TSource > field , int skip , int ? limit = null )
577
+ public ProjectionDefinition < TSource > Slice ( FieldDefinition < TSource > field , int skip , int limit )
533
578
{
534
- var value = limit . HasValue ? ( BsonValue ) new BsonArray { skip , limit . Value } : skip ;
535
- return new SingleFieldProjectionDefinition < TSource > ( field , new BsonDocument ( "$slice" , value ) ) ;
579
+ return new SliceProjectionDefinition < TSource > ( field , skip , limit ) ;
580
+ }
581
+
582
+ /// <summary>
583
+ /// Creates an array slice projection.
584
+ /// </summary>
585
+ /// <param name="field">The field.</param>
586
+ /// <param name="limit">The limit.</param>
587
+ /// <returns>
588
+ /// An array slice projection.
589
+ /// </returns>
590
+ public ProjectionDefinition < TSource > Slice ( Expression < Func < TSource , object > > field , int limit )
591
+ {
592
+ return Slice ( new ExpressionFieldDefinition < TSource > ( field ) , limit ) ;
536
593
}
537
594
538
595
/// <summary>
@@ -544,7 +601,7 @@ public ProjectionDefinition<TSource> Slice(FieldDefinition<TSource> field, int s
544
601
/// <returns>
545
602
/// An array slice projection.
546
603
/// </returns>
547
- public ProjectionDefinition < TSource > Slice ( Expression < Func < TSource , object > > field , int skip , int ? limit = null )
604
+ public ProjectionDefinition < TSource > Slice ( Expression < Func < TSource , object > > field , int skip , int limit )
548
605
{
549
606
return Slice ( new ExpressionFieldDefinition < TSource > ( field ) , skip , limit ) ;
550
607
}
@@ -560,12 +617,22 @@ public CombinedProjectionDefinition(IEnumerable<ProjectionDefinition<TSource>> p
560
617
}
561
618
562
619
public override BsonDocument Render ( IBsonSerializer < TSource > sourceSerializer , IBsonSerializerRegistry serializerRegistry , LinqProvider linqProvider )
620
+ {
621
+ return Render ( projection => projection . Render ( sourceSerializer , serializerRegistry , linqProvider ) ) ;
622
+ }
623
+
624
+ internal override BsonDocument RenderForFind ( IBsonSerializer < TSource > sourceSerializer , IBsonSerializerRegistry serializerRegistry , LinqProvider linqProvider )
625
+ {
626
+ return Render ( projection => projection . RenderForFind ( sourceSerializer , serializerRegistry , linqProvider ) ) ;
627
+ }
628
+
629
+ private BsonDocument Render ( Func < ProjectionDefinition < TSource > , BsonDocument > renderer )
563
630
{
564
631
var document = new BsonDocument ( ) ;
565
632
566
633
foreach ( var projection in _projections )
567
634
{
568
- var renderedProjection = projection . Render ( sourceSerializer , serializerRegistry , linqProvider ) ;
635
+ var renderedProjection = renderer ( projection ) ;
569
636
570
637
foreach ( var element in renderedProjection . Elements )
571
638
{
@@ -650,4 +717,53 @@ public override BsonDocument Render(IBsonSerializer<TSource> sourceSerializer, I
650
717
return new BsonDocument ( renderedField . FieldName , _value ) ;
651
718
}
652
719
}
720
+
721
+ internal sealed class SliceProjectionDefinition < TSource > : ProjectionDefinition < TSource >
722
+ {
723
+ private readonly FieldDefinition < TSource > _field ;
724
+ private readonly BsonValue _limit ;
725
+ private readonly BsonValue _skip ;
726
+
727
+ public SliceProjectionDefinition ( FieldDefinition < TSource > field , BsonValue limit )
728
+ {
729
+ _field = Ensure . IsNotNull ( field , nameof ( field ) ) ;
730
+ _limit = Ensure . IsNotNull ( limit , nameof ( limit ) ) ;
731
+ }
732
+
733
+ public SliceProjectionDefinition ( FieldDefinition < TSource > field , BsonValue skip , BsonValue limit )
734
+ {
735
+ _field = Ensure . IsNotNull ( field , nameof ( field ) ) ;
736
+ _skip = skip ; // can be null
737
+ _limit = Ensure . IsNotNull ( limit , nameof ( limit ) ) ;
738
+ }
739
+
740
+ public override BsonDocument Render ( IBsonSerializer < TSource > sourceSerializer , IBsonSerializerRegistry serializerRegistry , LinqProvider linqProvider )
741
+ {
742
+ return Render ( sourceSerializer , serializerRegistry , linqProvider , RenderArgs ) ;
743
+ }
744
+
745
+ internal override BsonDocument RenderForFind ( IBsonSerializer < TSource > sourceSerializer , IBsonSerializerRegistry serializerRegistry , LinqProvider linqProvider )
746
+ {
747
+ return Render ( sourceSerializer , serializerRegistry , linqProvider , RenderArgsForFind ) ;
748
+ }
749
+
750
+ private BsonDocument Render ( IBsonSerializer < TSource > sourceSerializer , IBsonSerializerRegistry serializerRegistry , LinqProvider linqProvider , Func < string , BsonValue > argsRenderer )
751
+ {
752
+ var renderedField = _field . Render ( sourceSerializer , serializerRegistry , linqProvider ) ;
753
+ var sliceArgs = argsRenderer ( renderedField . FieldName ) ;
754
+ return new BsonDocument ( renderedField . FieldName , new BsonDocument ( "$slice" , sliceArgs ) ) ;
755
+ }
756
+
757
+ private BsonValue RenderArgs ( string fieldName )
758
+ {
759
+ return _skip == null ?
760
+ new BsonArray { "$" + fieldName , _limit } :
761
+ new BsonArray { "$" + fieldName , _skip , _limit } ;
762
+ }
763
+
764
+ private BsonValue RenderArgsForFind ( string fieldName )
765
+ {
766
+ return _skip == null ? _limit : new BsonArray { _skip , _limit } ;
767
+ }
768
+ }
653
769
}
0 commit comments