44
44
import org .springframework .dao .OptimisticLockingFailureException ;
45
45
import org .springframework .dao .support .PersistenceExceptionTranslator ;
46
46
import org .springframework .data .convert .EntityReader ;
47
+ import org .springframework .data .domain .OffsetScrollPosition ;
48
+ import org .springframework .data .domain .Scroll ;
47
49
import org .springframework .data .geo .Distance ;
48
50
import org .springframework .data .geo .GeoResult ;
49
51
import org .springframework .data .geo .GeoResults ;
64
66
import org .springframework .data .mongodb .core .QueryOperations .DistinctQueryContext ;
65
67
import org .springframework .data .mongodb .core .QueryOperations .QueryContext ;
66
68
import org .springframework .data .mongodb .core .QueryOperations .UpdateContext ;
69
+ import org .springframework .data .mongodb .core .ScrollUtils .KeySetCursorQuery ;
67
70
import org .springframework .data .mongodb .core .aggregation .Aggregation ;
68
71
import org .springframework .data .mongodb .core .aggregation .AggregationOperationContext ;
69
72
import org .springframework .data .mongodb .core .aggregation .AggregationOptions ;
@@ -847,6 +850,48 @@ public <T> List<T> find(Query query, Class<T> entityClass, String collectionName
847
850
new QueryCursorPreparer (query , entityClass ));
848
851
}
849
852
853
+ @ Override
854
+ public <T > Scroll <T > scroll (Query query , Class <T > entityType ) {
855
+
856
+ Assert .notNull (entityType , "Entity type must not be null" );
857
+
858
+ return scroll (query , entityType , getCollectionName (entityType ));
859
+ }
860
+
861
+ @ Override
862
+ public <T > Scroll <T > scroll (Query query , Class <T > entityType , String collectionName ) {
863
+ return doScroll (query , entityType , entityType , collectionName );
864
+ }
865
+
866
+ <T > Scroll <T > doScroll (Query query , Class <?> sourceClass , Class <T > targetClass , String collectionName ) {
867
+
868
+ Assert .notNull (query , "Query must not be null" );
869
+ Assert .notNull (collectionName , "CollectionName must not be null" );
870
+ Assert .notNull (sourceClass , "Entity type must not be null" );
871
+ Assert .notNull (targetClass , "Target type must not be null" );
872
+
873
+ ReadDocumentCallback <T > callback = new ReadDocumentCallback <>(mongoConverter , targetClass , collectionName );
874
+ int limit = query .isLimited () ? query .getLimit () + 1 : Integer .MAX_VALUE ;
875
+
876
+ if (query .hasKeyset ()) {
877
+
878
+ KeySetCursorQuery keysetPaginationQuery = ScrollUtils .createKeysetPaginationQuery (query ,
879
+ operations .getIdPropertyName (sourceClass ));
880
+
881
+ List <T > result = doFind (collectionName , createDelegate (query ), keysetPaginationQuery .query (),
882
+ keysetPaginationQuery .fields (), sourceClass ,
883
+ new QueryCursorPreparer (query , keysetPaginationQuery .sort (), limit , 0 , sourceClass ), callback );
884
+
885
+ return ScrollUtils .createWindow (query .getSortObject (), query .getLimit (), result , operations );
886
+ }
887
+
888
+ List <T > result = doFind (collectionName , createDelegate (query ), query .getQueryObject (), query .getFieldsObject (),
889
+ sourceClass , new QueryCursorPreparer (query , query .getSortObject (), limit , query .getSkip (), sourceClass ),
890
+ callback );
891
+
892
+ return ScrollUtils .createWindow (result , query .getLimit (), OffsetScrollPosition .positionFunction (query .getSkip ()));
893
+ }
894
+
850
895
@ Nullable
851
896
@ Override
852
897
public <T > T findById (Object id , Class <T > entityClass ) {
@@ -953,7 +998,7 @@ public <T> GeoResults<T> geoNear(NearQuery near, Class<?> domainType, String col
953
998
optionsBuilder .readPreference (near .getReadPreference ());
954
999
}
955
1000
956
- if (near .hasReadConcern ()) {
1001
+ if (near .hasReadConcern ()) {
957
1002
optionsBuilder .readConcern (near .getReadConcern ());
958
1003
}
959
1004
@@ -2837,13 +2882,24 @@ private static MongoConverter getDefaultMongoConverter(MongoDatabaseFactory fact
2837
2882
return converter ;
2838
2883
}
2839
2884
2840
- private Document getMappedSortObject (Query query , Class <?> type ) {
2885
+ @ Nullable
2886
+ private Document getMappedSortObject (@ Nullable Query query , Class <?> type ) {
2841
2887
2842
- if (query == null || ObjectUtils . isEmpty ( query . getSortObject ()) ) {
2888
+ if (query == null ) {
2843
2889
return null ;
2844
2890
}
2845
2891
2846
- return queryMapper .getMappedSort (query .getSortObject (), mappingContext .getPersistentEntity (type ));
2892
+ return getMappedSortObject (query .getSortObject (), type );
2893
+ }
2894
+
2895
+ @ Nullable
2896
+ private Document getMappedSortObject (Document sortObject , Class <?> type ) {
2897
+
2898
+ if (ObjectUtils .isEmpty (sortObject )) {
2899
+ return null ;
2900
+ }
2901
+
2902
+ return queryMapper .getMappedSort (sortObject , mappingContext .getPersistentEntity (type ));
2847
2903
}
2848
2904
2849
2905
/**
@@ -3199,11 +3255,23 @@ public T doWith(Document document) {
3199
3255
class QueryCursorPreparer implements CursorPreparer {
3200
3256
3201
3257
private final Query query ;
3258
+
3259
+ private final Document sortObject ;
3260
+
3261
+ private final int limit ;
3262
+
3263
+ private final long skip ;
3202
3264
private final @ Nullable Class <?> type ;
3203
3265
3204
3266
QueryCursorPreparer (Query query , @ Nullable Class <?> type ) {
3267
+ this (query , query .getSortObject (), query .getLimit (), query .getSkip (), type );
3268
+ }
3205
3269
3270
+ QueryCursorPreparer (Query query , Document sortObject , int limit , long skip , @ Nullable Class <?> type ) {
3206
3271
this .query = query ;
3272
+ this .sortObject = sortObject ;
3273
+ this .limit = limit ;
3274
+ this .skip = skip ;
3207
3275
this .type = type ;
3208
3276
}
3209
3277
@@ -3218,20 +3286,20 @@ public FindIterable<Document> prepare(FindIterable<Document> iterable) {
3218
3286
3219
3287
Meta meta = query .getMeta ();
3220
3288
HintFunction hintFunction = HintFunction .from (query .getHint ());
3221
- if (query . getSkip () <= 0 && query . getLimit () <= 0 && ObjectUtils .isEmpty (query . getSortObject () )
3222
- && hintFunction . isEmpty () && ! meta . hasValues () && query .getCollation ().isEmpty ()) {
3289
+ if (skip <= 0 && limit <= 0 && ObjectUtils .isEmpty (sortObject ) && hintFunction . isEmpty () && ! meta . hasValues ( )
3290
+ && query .getCollation ().isEmpty ()) {
3223
3291
return cursorToUse ;
3224
3292
}
3225
3293
3226
3294
try {
3227
- if (query . getSkip () > 0 ) {
3228
- cursorToUse = cursorToUse .skip ((int ) query . getSkip () );
3295
+ if (skip > 0 ) {
3296
+ cursorToUse = cursorToUse .skip ((int ) skip );
3229
3297
}
3230
- if (query . getLimit () > 0 ) {
3231
- cursorToUse = cursorToUse .limit (query . getLimit () );
3298
+ if (limit > 0 ) {
3299
+ cursorToUse = cursorToUse .limit (limit );
3232
3300
}
3233
- if (!ObjectUtils .isEmpty (query . getSortObject () )) {
3234
- Document sort = type != null ? getMappedSortObject (query , type ) : query . getSortObject () ;
3301
+ if (!ObjectUtils .isEmpty (sortObject )) {
3302
+ Document sort = type != null ? getMappedSortObject (sortObject , type ) : sortObject ;
3235
3303
cursorToUse = cursorToUse .sort (sort );
3236
3304
}
3237
3305
0 commit comments