diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 06aee31afc..9cf7734588 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -75,6 +75,7 @@ * @author Mark Paluch * @author David Julia * @author Divya Srivastava + * @author Gyungrai Wang */ public class QueryMapper { @@ -459,44 +460,18 @@ public T getPropertyValue(MongoPersistentProperty property) { } if (documentField.isIdField() && !documentField.isAssociation()) { - if (isDBObject(value)) { - DBObject valueDbo = (DBObject) value; - Document resultDbo = new Document(valueDbo.toMap()); - - if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) { - String inKey = valueDbo.containsField("$in") ? "$in" : "$nin"; - List ids = new ArrayList<>(); - for (Object id : (Iterable) valueDbo.get(inKey)) { - ids.add(convertId(id, getIdTypeForField(documentField))); - } - resultDbo.put(inKey, ids); - } else if (valueDbo.containsField("$ne")) { - resultDbo.put("$ne", convertId(valueDbo.get("$ne"), getIdTypeForField(documentField))); - } else { - return getMappedObject(resultDbo, Optional.empty()); - } - return resultDbo; + Document valueDbo = new Document(((DBObject) value).toMap()); + Document resultDbo = new Document(valueDbo); + + return convertIdField(valueDbo, resultDbo, documentField); } else if (isDocument(value)) { Document valueDbo = (Document) value; Document resultDbo = new Document(valueDbo); - if (valueDbo.containsKey("$in") || valueDbo.containsKey("$nin")) { - String inKey = valueDbo.containsKey("$in") ? "$in" : "$nin"; - List ids = new ArrayList<>(); - for (Object id : (Iterable) valueDbo.get(inKey)) { - ids.add(convertId(id, getIdTypeForField(documentField))); - } - resultDbo.put(inKey, ids); - } else if (valueDbo.containsKey("$ne")) { - resultDbo.put("$ne", convertId(valueDbo.get("$ne"), getIdTypeForField(documentField))); - } else { - return getMappedObject(resultDbo, Optional.empty()); - } - return resultDbo; - + return convertIdField(valueDbo, resultDbo, documentField); } else { return convertId(value, getIdTypeForField(documentField)); } @@ -517,10 +492,44 @@ else if (isDocument(value)) { return convertSimpleOrDocument(value, documentField.getPropertyEntity()); } + private Document convertIdField(Document valueDbo, Document resultDbo, Field documentField) { + if (valueDbo.containsKey("$in") || valueDbo.containsKey("$nin")) { + String inKey = valueDbo.containsKey("$in") ? "$in" : "$nin"; + List ids = new ArrayList<>(); + for (Object id : (Iterable) valueDbo.get(inKey)) { + ids.add(convertId(id, getIdTypeForField(documentField))); + } + resultDbo.put(inKey, ids); + } else if (valueDbo.containsKey("$ne")) { + resultDbo.put("$ne", convertId(valueDbo.get("$ne"), getIdTypeForField(documentField))); + } else if (containsCompareOperator(valueDbo)) { + if (valueDbo.containsKey("$gt")) { + resultDbo.put("$gt", convertId(valueDbo.get("$gt"), getIdTypeForField(documentField))); + } + if (valueDbo.containsKey("$gte")) { + resultDbo.put("$gte", convertId(valueDbo.get("$gte"), getIdTypeForField(documentField))); + } + if (valueDbo.containsKey("$lt")) { + resultDbo.put("$lt", convertId(valueDbo.get("$lt"), getIdTypeForField(documentField))); + } + if (valueDbo.containsKey("$lte")) { + resultDbo.put("$lte", convertId(valueDbo.get("$lte"), getIdTypeForField(documentField))); + } + } else { + return getMappedObject(resultDbo, Optional.empty()); + } + return resultDbo; + } + private boolean isIdField(Field documentField) { return documentField.getProperty() != null && documentField.getProperty().isIdProperty(); } + private boolean containsCompareOperator(Document document) { + return document.containsKey("$gt") || document.containsKey("$gte") || document.containsKey("$lt") + || document.containsKey("$lte"); + } + private Class getIdTypeForField(Field documentField) { return isIdField(documentField) ? documentField.getProperty().getFieldType() : ObjectId.class; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index fc0345b3d4..81c1185c86 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -70,6 +70,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author David Julia + * @author Gyungrai Wang */ public class QueryMapperUnitTests { @@ -127,6 +128,80 @@ void handlesObjectIdCapableBigIntegerIdsCorrectly() { assertThat(result).containsEntry("_id", id); } + @Test // ISSUE-4490 + void translates$GtCorrectly() { + + Criteria criteria = where("id").gt(new ObjectId().toString()); + + org.bson.Document query = new org.bson.Document("id", new ObjectId().toString()); + org.bson.Document result = mapper.getMappedObject(criteria.getCriteriaObject(), + context.getPersistentEntity(IdWrapper.class)); + Object object = result.get("_id"); + assertThat(object).isInstanceOf(org.bson.Document.class); + org.bson.Document document = (org.bson.Document) object; + assertThat(document.get("$gt")).isInstanceOf(ObjectId.class); + } + + @Test // ISSUE-4490 + void translates$GteCorrectly() { + + Criteria criteria = where("id").gte(new ObjectId().toString()); + + org.bson.Document query = new org.bson.Document("id", new ObjectId().toString()); + org.bson.Document result = mapper.getMappedObject(criteria.getCriteriaObject(), + context.getPersistentEntity(IdWrapper.class)); + Object object = result.get("_id"); + assertThat(object).isInstanceOf(org.bson.Document.class); + org.bson.Document document = (org.bson.Document) object; + assertThat(document.get("$gte")).isInstanceOf(ObjectId.class); + } + + @Test // ISSUE-4490 + void translates$LteCorrectly() { + + Criteria criteria = where("id").lte(new ObjectId().toString()); + + org.bson.Document query = new org.bson.Document("id", new ObjectId().toString()); + org.bson.Document result = mapper.getMappedObject(criteria.getCriteriaObject(), + context.getPersistentEntity(IdWrapper.class)); + Object object = result.get("_id"); + assertThat(object).isInstanceOf(org.bson.Document.class); + org.bson.Document document = (org.bson.Document) object; + assertThat(document.get("$lte")).isInstanceOf(ObjectId.class); + } + + @Test // ISSUE-4490 + void translates$LtCorrectly() { + + Criteria criteria = where("id").lt(new ObjectId().toString()); + + org.bson.Document query = new org.bson.Document("id", new ObjectId().toString()); + org.bson.Document result = mapper.getMappedObject(criteria.getCriteriaObject(), + context.getPersistentEntity(IdWrapper.class)); + Object object = result.get("_id"); + assertThat(object).isInstanceOf(org.bson.Document.class); + org.bson.Document document = (org.bson.Document) object; + assertThat(document.get("$lt")).isInstanceOf(ObjectId.class); + } + + @Test // ISSUE-4490 + void translatesMultipleCompareOperatorsCorrectly() { + + Criteria criteria = where("id").lt(new ObjectId().toString()).lte(new ObjectId().toString()) + .gt(new ObjectId().toString()).gte(new ObjectId().toString()); + + org.bson.Document query = new org.bson.Document("id", new ObjectId().toString()); + org.bson.Document result = mapper.getMappedObject(criteria.getCriteriaObject(), + context.getPersistentEntity(IdWrapper.class)); + Object object = result.get("_id"); + assertThat(object).isInstanceOf(org.bson.Document.class); + org.bson.Document document = (org.bson.Document) object; + assertThat(document.get("$lt")).isInstanceOf(ObjectId.class); + assertThat(document.get("$lte")).isInstanceOf(ObjectId.class); + assertThat(document.get("$gt")).isInstanceOf(ObjectId.class); + assertThat(document.get("$gte")).isInstanceOf(ObjectId.class); + } + @Test // DATAMONGO-278 void translates$NeCorrectly() {