34
34
import org .springframework .data .mapping .context .MappingContext ;
35
35
import org .springframework .data .mapping .model .SpELContext ;
36
36
import org .springframework .data .mongodb .core .convert .ReferenceLoader .DocumentReferenceQuery ;
37
+ import org .springframework .data .mongodb .core .convert .ReferenceLoader .NoResultsFilter ;
37
38
import org .springframework .data .mongodb .core .convert .ReferenceResolver .MongoEntityReader ;
38
39
import org .springframework .data .mongodb .core .convert .ReferenceResolver .ReferenceCollection ;
39
40
import org .springframework .data .mongodb .core .mapping .DocumentReference ;
40
- import org .springframework .data .mongodb .core .mapping .FieldName ;
41
41
import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
42
42
import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
43
43
import org .springframework .data .mongodb .util .BsonUtils ;
49
49
import org .springframework .expression .EvaluationContext ;
50
50
import org .springframework .lang .Nullable ;
51
51
import org .springframework .util .Assert ;
52
+ import org .springframework .util .ObjectUtils ;
52
53
import org .springframework .util .StringUtils ;
53
54
54
55
import com .mongodb .DBRef ;
65
66
*/
66
67
public final class ReferenceLookupDelegate {
67
68
68
- private static final Document NO_RESULTS_PREDICATE = new Document (FieldName .ID .name (),
69
- new Document ("$exists" , false ));
70
-
71
69
private final MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > mappingContext ;
72
70
private final SpELContext spELContext ;
73
71
private final ParameterBindingDocumentCodec codec ;
@@ -104,18 +102,15 @@ public ReferenceLookupDelegate(
104
102
public Object readReference (MongoPersistentProperty property , Object source , LookupFunction lookupFunction ,
105
103
MongoEntityReader entityReader ) {
106
104
107
- Object value = source instanceof DocumentReferenceSource documentReferenceSource ? documentReferenceSource .getTargetSource ()
105
+ Object value = source instanceof DocumentReferenceSource documentReferenceSource
106
+ ? documentReferenceSource .getTargetSource ()
108
107
: source ;
109
108
110
- // GH-4612 no need to query database if target collection is empty
111
- if (value != null && property .isCollectionLike () && (value instanceof Collection <?> c ) && c .isEmpty ()) {
112
- return new ArrayList <>();
113
- }
114
-
115
- DocumentReferenceQuery filter = computeFilter (property , source , spELContext );
116
- ReferenceCollection referenceCollection = computeReferenceContext (property , value , spELContext );
109
+ Iterable <Document > result = retrieveRawDocuments (property , source , lookupFunction , value );
117
110
118
- Iterable <Document > result = lookupFunction .apply (filter , referenceCollection );
111
+ if (result == null ) {
112
+ return null ;
113
+ }
119
114
120
115
if (property .isCollectionLike ()) {
121
116
return entityReader .read (result , property .getTypeInformation ());
@@ -129,6 +124,19 @@ public Object readReference(MongoPersistentProperty property, Object source, Loo
129
124
return resultValue != null ? entityReader .read (resultValue , property .getTypeInformation ()) : null ;
130
125
}
131
126
127
+ @ Nullable
128
+ private Iterable <Document > retrieveRawDocuments (MongoPersistentProperty property , Object source ,
129
+ LookupFunction lookupFunction , Object value ) {
130
+
131
+ DocumentReferenceQuery filter = computeFilter (property , source , spELContext );
132
+ if (filter instanceof NoResultsFilter ) {
133
+ return Collections .emptyList ();
134
+ }
135
+
136
+ ReferenceCollection referenceCollection = computeReferenceContext (property , value , spELContext );
137
+ return lookupFunction .apply (filter , referenceCollection );
138
+ }
139
+
132
140
private ReferenceCollection computeReferenceContext (MongoPersistentProperty property , Object value ,
133
141
SpELContext spELContext ) {
134
142
@@ -278,7 +286,7 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so
278
286
Collection <Object > objects = (Collection <Object >) value ;
279
287
280
288
if (objects .isEmpty ()) {
281
- return new ListDocumentReferenceQuery ( NO_RESULTS_PREDICATE , sort );
289
+ return DocumentReferenceQuery . forNoResult ( );
282
290
}
283
291
284
292
List <Document > ors = new ArrayList <>(objects .size ());
@@ -293,11 +301,11 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so
293
301
294
302
if (property .isMap () && value instanceof Map ) {
295
303
296
- Set <Entry <Object , Object >> entries = ((Map <Object , Object >) value ).entrySet ();
297
- if (entries .isEmpty ()) {
298
- return new MapDocumentReferenceQuery (NO_RESULTS_PREDICATE , sort , Collections .emptyMap ());
304
+ if (ObjectUtils .isEmpty (value )) {
305
+ return DocumentReferenceQuery .forNoResult ();
299
306
}
300
307
308
+ Set <Entry <Object , Object >> entries = ((Map <Object , Object >) value ).entrySet ();
301
309
Map <Object , Document > filterMap = new LinkedHashMap <>(entries .size ());
302
310
303
311
for (Entry <Object , Object > entry : entries ) {
@@ -411,8 +419,7 @@ public Bson getSort() {
411
419
public Iterable <Document > restoreOrder (Iterable <Document > documents ) {
412
420
413
421
Map <String , Object > targetMap = new LinkedHashMap <>();
414
- List <Document > collected = documents instanceof List <Document > list ? list
415
- : Streamable .of (documents ).toList ();
422
+ List <Document > collected = documents instanceof List <Document > list ? list : Streamable .of (documents ).toList ();
416
423
417
424
for (Entry <Object , Document > filterMapping : filterOrderMap .entrySet ()) {
418
425
@@ -444,8 +451,7 @@ public ListDocumentReferenceQuery(Document query, Document sort) {
444
451
@ Override
445
452
public Iterable <Document > restoreOrder (Iterable <Document > documents ) {
446
453
447
- List <Document > target = documents instanceof List <Document > list ? list
448
- : Streamable .of (documents ).toList ();
454
+ List <Document > target = documents instanceof List <Document > list ? list : Streamable .of (documents ).toList ();
449
455
450
456
if (!sort .isEmpty () || !query .containsKey ("$or" )) {
451
457
return target ;
0 commit comments