3434import org .springframework .data .mapping .context .MappingContext ;
3535import org .springframework .data .mapping .model .SpELContext ;
3636import org .springframework .data .mongodb .core .convert .ReferenceLoader .DocumentReferenceQuery ;
37+ import org .springframework .data .mongodb .core .convert .ReferenceLoader .NoResultsFilter ;
3738import org .springframework .data .mongodb .core .convert .ReferenceResolver .MongoEntityReader ;
3839import org .springframework .data .mongodb .core .convert .ReferenceResolver .ReferenceCollection ;
3940import org .springframework .data .mongodb .core .mapping .DocumentReference ;
40- import org .springframework .data .mongodb .core .mapping .FieldName ;
4141import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
4242import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
4343import org .springframework .data .mongodb .util .BsonUtils ;
4949import org .springframework .expression .EvaluationContext ;
5050import org .springframework .lang .Nullable ;
5151import org .springframework .util .Assert ;
52+ import org .springframework .util .ObjectUtils ;
5253import org .springframework .util .StringUtils ;
5354
5455import com .mongodb .DBRef ;
6566 */
6667public final class ReferenceLookupDelegate {
6768
68- private static final Document NO_RESULTS_PREDICATE = new Document (FieldName .ID .name (),
69- new Document ("$exists" , false ));
70-
7169 private final MappingContext <? extends MongoPersistentEntity <?>, MongoPersistentProperty > mappingContext ;
7270 private final SpELContext spELContext ;
7371 private final ParameterBindingDocumentCodec codec ;
@@ -104,18 +102,15 @@ public ReferenceLookupDelegate(
104102 public Object readReference (MongoPersistentProperty property , Object source , LookupFunction lookupFunction ,
105103 MongoEntityReader entityReader ) {
106104
107- Object value = source instanceof DocumentReferenceSource documentReferenceSource ? documentReferenceSource .getTargetSource ()
105+ Object value = source instanceof DocumentReferenceSource documentReferenceSource
106+ ? documentReferenceSource .getTargetSource ()
108107 : source ;
109108
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 );
117110
118- Iterable <Document > result = lookupFunction .apply (filter , referenceCollection );
111+ if (result == null ) {
112+ return null ;
113+ }
119114
120115 if (property .isCollectionLike ()) {
121116 return entityReader .read (result , property .getTypeInformation ());
@@ -129,6 +124,19 @@ public Object readReference(MongoPersistentProperty property, Object source, Loo
129124 return resultValue != null ? entityReader .read (resultValue , property .getTypeInformation ()) : null ;
130125 }
131126
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+
132140 private ReferenceCollection computeReferenceContext (MongoPersistentProperty property , Object value ,
133141 SpELContext spELContext ) {
134142
@@ -278,7 +286,7 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so
278286 Collection <Object > objects = (Collection <Object >) value ;
279287
280288 if (objects .isEmpty ()) {
281- return new ListDocumentReferenceQuery ( NO_RESULTS_PREDICATE , sort );
289+ return DocumentReferenceQuery . forNoResult ( );
282290 }
283291
284292 List <Document > ors = new ArrayList <>(objects .size ());
@@ -293,11 +301,11 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so
293301
294302 if (property .isMap () && value instanceof Map ) {
295303
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 ();
299306 }
300307
308+ Set <Entry <Object , Object >> entries = ((Map <Object , Object >) value ).entrySet ();
301309 Map <Object , Document > filterMap = new LinkedHashMap <>(entries .size ());
302310
303311 for (Entry <Object , Object > entry : entries ) {
@@ -411,8 +419,7 @@ public Bson getSort() {
411419 public Iterable <Document > restoreOrder (Iterable <Document > documents ) {
412420
413421 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 ();
416423
417424 for (Entry <Object , Document > filterMapping : filterOrderMap .entrySet ()) {
418425
@@ -444,8 +451,7 @@ public ListDocumentReferenceQuery(Document query, Document sort) {
444451 @ Override
445452 public Iterable <Document > restoreOrder (Iterable <Document > documents ) {
446453
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 ();
449455
450456 if (!sort .isEmpty () || !query .containsKey ("$or" )) {
451457 return target ;
0 commit comments