|
15 | 15 | */
|
16 | 16 | package org.springframework.data.mongodb.core.convert;
|
17 | 17 |
|
18 |
| -import java.util.ArrayList; |
19 |
| -import java.util.Arrays; |
20 |
| -import java.util.Collections; |
21 |
| -import java.util.HashSet; |
22 |
| -import java.util.Iterator; |
23 |
| -import java.util.LinkedHashMap; |
24 |
| -import java.util.List; |
25 |
| -import java.util.Map; |
| 18 | +import java.util.*; |
26 | 19 | import java.util.Map.Entry;
|
27 |
| -import java.util.Optional; |
28 |
| -import java.util.Set; |
29 | 20 | import java.util.regex.Matcher;
|
30 | 21 | import java.util.regex.Pattern;
|
31 | 22 |
|
|
36 | 27 | import org.springframework.core.convert.ConversionService;
|
37 | 28 | import org.springframework.core.convert.converter.Converter;
|
38 | 29 | import org.springframework.data.domain.Example;
|
| 30 | +import org.springframework.data.geo.Point; |
39 | 31 | import org.springframework.data.mapping.Association;
|
40 | 32 | import org.springframework.data.mapping.MappingException;
|
41 | 33 | import org.springframework.data.mapping.PersistentEntity;
|
@@ -1290,4 +1282,97 @@ public String convert(MongoPersistentProperty source) {
|
1290 | 1282 | public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
|
1291 | 1283 | return mappingContext;
|
1292 | 1284 | }
|
| 1285 | + |
| 1286 | + public static Document processCountFilter(Document source) { |
| 1287 | + |
| 1288 | + Document target = new Document(); |
| 1289 | + for (Entry<String, Object> entry : source.entrySet()) { |
| 1290 | + |
| 1291 | + if (entry.getValue() instanceof Document) { |
| 1292 | + |
| 1293 | + Document theValue = (Document) entry.getValue(); |
| 1294 | + if (containsNear(theValue)) { |
| 1295 | + target.putAll(createGeoWithin(entry.getKey(), theValue)); |
| 1296 | + } else { |
| 1297 | + target.put(entry.getKey(), entry.getValue()); |
| 1298 | + } |
| 1299 | + } else if (entry.getValue() instanceof Collection) { |
| 1300 | + |
| 1301 | + Collection<Object> tmp = new ArrayList<>(); |
| 1302 | + for (Object val : (Collection) entry.getValue()) { |
| 1303 | + if (val instanceof Document) { |
| 1304 | + tmp.add(processCountFilter((Document) val)); |
| 1305 | + } else { |
| 1306 | + tmp.add(val); |
| 1307 | + } |
| 1308 | + } |
| 1309 | + target.put(entry.getKey(), tmp); |
| 1310 | + } else { |
| 1311 | + target.put(entry.getKey(), entry.getValue()); |
| 1312 | + } |
| 1313 | + } |
| 1314 | + return target; |
| 1315 | + } |
| 1316 | + |
| 1317 | + private static Document createGeoWithin(String key, Document source) { |
| 1318 | + |
| 1319 | + boolean spheric = source.containsKey("$nearSphere"); |
| 1320 | + Object $near = spheric ? source.get("$nearSphere") : source.get("$near"); |
| 1321 | + |
| 1322 | + Number maxDistance = source.containsKey("$maxDistance") ? (Number) source.get("$maxDistance") : Double.MAX_VALUE; |
| 1323 | + List<Object> $centerMax = Arrays.asList(toCenterCoordinates($near), maxDistance); |
| 1324 | + Document $geoWithinMax = new Document("$geoWithin", |
| 1325 | + new Document(spheric ? "$centerSphere" : "$center", $centerMax)); |
| 1326 | + |
| 1327 | + if (!containsNearWithMinDistance(source)) { |
| 1328 | + return new Document(key, $geoWithinMax); |
| 1329 | + } |
| 1330 | + |
| 1331 | + Number minDistance = (Number) source.get("$minDistance"); |
| 1332 | + List<Object> $centerMin = Arrays.asList(toCenterCoordinates($near), minDistance); |
| 1333 | + Document $geoWithinMin = new Document("$geoWithin", |
| 1334 | + new Document(spheric ? "$centerSphere" : "$center", $centerMin)); |
| 1335 | + |
| 1336 | + List<Document> criteria = new ArrayList<>(); |
| 1337 | + criteria.add(new Document("$nor", Arrays.asList(new Document(key, $geoWithinMin)))); |
| 1338 | + criteria.add(new Document(key, $geoWithinMax)); |
| 1339 | + return new Document("$and", criteria); |
| 1340 | + } |
| 1341 | + |
| 1342 | + private static boolean containsNear(Document source) { |
| 1343 | + |
| 1344 | + if (source.containsKey("$near") || source.containsKey("$nearSphere")) { |
| 1345 | + return true; |
| 1346 | + } |
| 1347 | + |
| 1348 | + return false; |
| 1349 | + } |
| 1350 | + |
| 1351 | + private static boolean containsNearWithMinDistance(Document source) { |
| 1352 | + |
| 1353 | + if (!containsNear(source)) { |
| 1354 | + return false; |
| 1355 | + } |
| 1356 | + |
| 1357 | + return source.containsKey("$minDistance"); |
| 1358 | + } |
| 1359 | + |
| 1360 | + private static Object toCenterCoordinates(Object value) { |
| 1361 | + |
| 1362 | + if (ObjectUtils.isArray(value)) { |
| 1363 | + return value; |
| 1364 | + } |
| 1365 | + |
| 1366 | + if (value instanceof Point) { |
| 1367 | + return Arrays.asList(((Point) value).getX(), ((Point) value).getY()); |
| 1368 | + } |
| 1369 | + |
| 1370 | + if (value instanceof Document && ((Document) value).containsKey("x")) { |
| 1371 | + |
| 1372 | + Document point = (Document) value; |
| 1373 | + return Arrays.asList(point.get("x"), point.get("y")); |
| 1374 | + } |
| 1375 | + |
| 1376 | + return value; |
| 1377 | + } |
1293 | 1378 | }
|
0 commit comments