diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index 9fce3ddbb..8438e201b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 the original author or authors. + * Copyright 2010-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import static org.springframework.util.ObjectUtils.*; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -35,13 +36,14 @@ import com.mongodb.DBObject; /** * Class to easily construct MongoDB update clauses. - * + * * @author Thomas Risberg * @author Mark Pollack * @author Oliver Gierke * @author Becca Gaspard * @author Christoph Strobl * @author Thomas Darimont + * @author Alexey Plotnik */ public class Update { @@ -55,7 +57,7 @@ public class Update { /** * Static factory method to create an Update using the provided key - * + * * @param key * @return */ @@ -69,7 +71,7 @@ public class Update { * {@literal $set}. This means fields not given in the {@link DBObject} will be nulled when executing the update. To * create an only-updating {@link Update} instance of a {@link DBObject}, call {@link #set(String, Object)} for each * value in it. - * + * * @param object the source {@link DBObject} to create the update from. * @param exclude the fields to exclude. * @return @@ -99,7 +101,7 @@ public class Update { /** * Update using the {@literal $set} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/set/ * @param key * @param value @@ -112,7 +114,7 @@ public class Update { /** * Update using the {@literal $setOnInsert} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/setOnInsert/ * @param key * @param value @@ -125,7 +127,7 @@ public class Update { /** * Update using the {@literal $unset} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/unset/ * @param key * @return @@ -137,7 +139,7 @@ public class Update { /** * Update using the {@literal $inc} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/inc/ * @param key * @param inc @@ -150,7 +152,7 @@ public class Update { /** * Update using the {@literal $push} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/push/ * @param key * @param value @@ -165,7 +167,7 @@ public class Update { * Update using {@code $push} modifier.
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values as well as using * {@code $position}. - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/push/ * @see http://docs.mongodb.org/manual/reference/operator/update/each/ * @param key @@ -183,7 +185,7 @@ public class Update { * Update using the {@code $pushAll} update modifier.
* Note: In mongodb 2.4 the usage of {@code $pushAll} has been deprecated in favor of {@code $push $each}. * {@link #push(String)}) returns a builder that can be used to populate the {@code $each} object. - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/pushAll/ * @param key * @param values @@ -197,7 +199,7 @@ public class Update { /** * Update using {@code $addToSet} modifier.
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values - * + * * @param key * @return * @since 1.5 @@ -208,7 +210,7 @@ public class Update { /** * Update using the {@literal $addToSet} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/addToSet/ * @param key * @param value @@ -221,7 +223,7 @@ public class Update { /** * Update using the {@literal $pop} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/pop/ * @param key * @param pos @@ -234,7 +236,7 @@ public class Update { /** * Update using the {@literal $pull} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/pull/ * @param key * @param value @@ -247,7 +249,7 @@ public class Update { /** * Update using the {@literal $pullAll} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/pullAll/ * @param key * @param values @@ -260,7 +262,7 @@ public class Update { /** * Update using the {@literal $rename} update modifier - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/rename/ * @param oldName * @param newName @@ -273,7 +275,7 @@ public class Update { /** * Update given key to current date using {@literal $currentDate} modifier. - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/currentDate/ * @param key * @return @@ -287,7 +289,7 @@ public class Update { /** * Update given key to current date using {@literal $currentDate : { $type : "timestamp" }} modifier. - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/currentDate/ * @param key * @return @@ -301,7 +303,7 @@ public class Update { /** * Multiply the value of given key by the given number. - * + * * @see http://docs.mongodb.org/manual/reference/operator/update/mul/ * @param key must not be {@literal null}. * @param multiplier must not be {@literal null}. @@ -314,38 +316,44 @@ public class Update { addMultiFieldOperation("$mul", key, multiplier.doubleValue()); return this; } - + /** - * Update using the {@literal $max} update modifier + * Update given key to the {@code value} if the {@code value} is greater than the current value of the field. * * @see http://docs.mongodb.org/manual/reference/operator/update/max/ - * @param key - * @param value + * @see https://docs.mongodb.org/manual/reference/bson-types/#faq-dev-compare-order-for-bson-types + * @param key must not be {@literal null}. + * @param value must not be {@literal null}. * @return + * @since 1.10 */ public Update max(String key, Object value) { - Assert.notNull(value, "Value must not be 'null'."); + + Assert.notNull(value, "Value for max operation must not be 'null'."); addMultiFieldOperation("$max", key, value); return this; } /** - * Update using the {@literal $max} update modifier + * Update given key to the {@code value} if the {@code value} is less than the current value of the field. * * @see http://docs.mongodb.org/manual/reference/operator/update/min/ - * @param key - * @param value + * @see https://docs.mongodb.org/manual/reference/bson-types/#faq-dev-compare-order-for-bson-types + * @param key must not be {@literal null}. + * @param value must not be {@literal null}. * @return + * @since 1.10 */ public Update min(String key, Object value) { - Assert.notNull(value, "Value must not be 'null'."); + + Assert.notNull(value, "Value for min operation must not be 'null'."); addMultiFieldOperation("$min", key, value); return this; } /** * The operator supports bitwise {@code and}, bitwise {@code or}, and bitwise {@code xor} operations. - * + * * @param key * @return * @since 1.7 @@ -360,7 +368,7 @@ public class Update { /** * This method is not called anymore rather override {@link #addMultiFieldOperation(String, String, Object)}. - * + * * @param operator * @param key * @param value @@ -399,7 +407,7 @@ public class Update { /** * Determine if a given {@code key} will be touched on execution. - * + * * @param key * @return */ @@ -409,7 +417,7 @@ public class Update { /** * Inspects given {@code key} for '$'. - * + * * @param key * @return */ @@ -417,7 +425,7 @@ public class Update { return StringUtils.startsWithIgnoreCase(key, "$"); } - /* + /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -426,7 +434,7 @@ public class Update { return getUpdateObject().hashCode(); } - /* + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -456,7 +464,7 @@ public class Update { /** * Modifiers holds a distinct collection of {@link Modifier} - * + * * @author Christoph Strobl * @author Thomas Darimont */ @@ -506,7 +514,7 @@ public class Update { /** * Marker interface of nested commands. - * + * * @author Christoph Strobl */ public static interface Modifier { @@ -524,7 +532,7 @@ public class Update { /** * Implementation of {@link Modifier} representing {@code $each}. - * + * * @author Christoph Strobl * @author Thomas Darimont */ @@ -567,7 +575,7 @@ public class Update { return this.values; } - /* + /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -576,7 +584,7 @@ public class Update { return nullSafeHashCode(values); } - /* + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -597,7 +605,7 @@ public class Update { /** * {@link Modifier} implementation used to propagate {@code $position}. - * + * * @author Christoph Strobl * @since 1.7 */ @@ -622,7 +630,7 @@ public class Update { /** * Builder for creating {@code $push} modifiers - * + * * @author Christoph Strobl * @author Thomas Darimont */ @@ -638,7 +646,7 @@ public class Update { /** * Propagates {@code $each} to {@code $push} - * + * * @param values * @return */ @@ -650,7 +658,7 @@ public class Update { /** * Forces values to be added at the given {@literal position}. - * + * * @param position needs to be greater than or equal to zero. * @return * @since 1.7 @@ -668,7 +676,7 @@ public class Update { /** * Forces values to be added at given {@literal position}. - * + * * @param position can be {@literal null} which will be appended at the last position. * @return * @since 1.7 @@ -686,7 +694,7 @@ public class Update { /** * Propagates {@link #value(Object)} to {@code $push} - * + * * @param values * @return */ @@ -694,7 +702,7 @@ public class Update { return Update.this.push(key, value); } - /* + /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -710,7 +718,7 @@ public class Update { return result; } - /* + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -741,7 +749,7 @@ public class Update { /** * Builder for creating {@code $addToSet} modifier. - * + * * @author Christoph Strobl * @since 1.5 */ @@ -755,7 +763,7 @@ public class Update { /** * Propagates {@code $each} to {@code $addToSet} - * + * * @param values * @return */ @@ -765,7 +773,7 @@ public class Update { /** * Propagates {@link #value(Object)} to {@code $addToSet} - * + * * @param values * @return */ @@ -795,7 +803,7 @@ public class Update { /** * Creates a new {@link BitwiseOperatorBuilder}. - * + * * @param reference must not be {@literal null} * @param key must not be {@literal null} */ @@ -810,7 +818,7 @@ public class Update { /** * Updates to the result of a bitwise and operation between the current value and the given one. - * + * * @param value * @return */ @@ -822,7 +830,7 @@ public class Update { /** * Updates to the result of a bitwise or operation between the current value and the given one. - * + * * @param value * @return */ @@ -834,7 +842,7 @@ public class Update { /** * Updates to the result of a bitwise xor operation between the current value and the given one. - * + * * @param value * @return */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 86ce2a08b..43ba0fe8c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -24,14 +24,17 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.core.query.Update.*; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import org.bson.types.ObjectId; @@ -94,7 +97,7 @@ import com.mongodb.WriteResult; /** * Integration test for {@link MongoTemplate}. - * + * * @author Oliver Gierke * @author Thomas Risberg * @author Amol Nayak @@ -102,6 +105,7 @@ import com.mongodb.WriteResult; * @author Thomas Darimont * @author Komi Innocent * @author Christoph Strobl + * @author Mark Paluch */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:infrastructure.xml") @@ -3164,6 +3168,194 @@ public class MongoTemplateTests { assertThat(template.findOne(query(where("id").is(wgj.id)), WithGeoJson.class).point, is(equalTo(wgj.point))); } + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesDateValueCorrectlyWhenUsingMinOperator() { + + Calendar cal = Calendar.getInstance(Locale.US); + cal.set(2013, 10, 13, 0, 0, 0); + + TypeWithDate twd = new TypeWithDate(); + twd.date = new Date(); + template.save(twd); + template.updateFirst(query(where("id").is(twd.id)), new Update().min("date", cal.getTime()), TypeWithDate.class); + + TypeWithDate loaded = template.find(query(where("id").is(twd.id)), TypeWithDate.class).get(0); + assertThat(loaded.date, equalTo(cal.getTime())); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesNumericValueCorrectlyWhenUsingMinOperator() { + + TypeWithNumbers twn = new TypeWithNumbers(); + twn.byteVal = 100; + twn.doubleVal = 200D; + twn.floatVal = 300F; + twn.intVal = 400; + twn.longVal = 500L; + + // Note that $min operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules. + twn.bigIntegerVal = new BigInteger("600"); + twn.bigDeciamVal = new BigDecimal("700.0"); + + template.save(twn); + + byte byteVal = 90; + Update update = new Update()// + .min("byteVal", byteVal) // + .min("doubleVal", 190D) // + .min("floatVal", 290F) // + .min("intVal", 390) // + .min("longVal", 490) // + .min("bigIntegerVal", new BigInteger("590")) // + .min("bigDeciamVal", new BigDecimal("690")) // + ; + + template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class); + + TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0); + assertThat(loaded.byteVal, equalTo(byteVal)); + assertThat(loaded.doubleVal, equalTo(190D)); + assertThat(loaded.floatVal, equalTo(290F)); + assertThat(loaded.intVal, equalTo(390)); + assertThat(loaded.longVal, equalTo(490L)); + assertThat(loaded.bigIntegerVal, equalTo(new BigInteger("590"))); + assertThat(loaded.bigDeciamVal, equalTo(new BigDecimal("690"))); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesDateValueCorrectlyWhenUsingMaxOperator() { + + Calendar cal = Calendar.getInstance(Locale.US); + cal.set(2013, 10, 13, 0, 0, 0); + + TypeWithDate twd = new TypeWithDate(); + twd.date = cal.getTime(); + template.save(twd); + + cal.set(2019, 10, 13, 0, 0, 0); + template.updateFirst(query(where("id").is(twd.id)), new Update().max("date", cal.getTime()), TypeWithDate.class); + + TypeWithDate loaded = template.find(query(where("id").is(twd.id)), TypeWithDate.class).get(0); + assertThat(loaded.date, equalTo(cal.getTime())); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesNumericValueCorrectlyWhenUsingMaxOperator() { + + TypeWithNumbers twn = new TypeWithNumbers(); + twn.byteVal = 100; + twn.doubleVal = 200D; + twn.floatVal = 300F; + twn.intVal = 400; + twn.longVal = 500L; + + // Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules. + twn.bigIntegerVal = new BigInteger("600"); + twn.bigDeciamVal = new BigDecimal("700.0"); + + template.save(twn); + + byte byteVal = 101; + Update update = new Update()// + .max("byteVal", byteVal) // + .max("doubleVal", 290D) // + .max("floatVal", 390F) // + .max("intVal", 490) // + .max("longVal", 590) // + .max("bigIntegerVal", new BigInteger("690")) // + .max("bigDeciamVal", new BigDecimal("790")) // + ; + + template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class); + + TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0); + assertThat(loaded.byteVal, equalTo(byteVal)); + assertThat(loaded.doubleVal, equalTo(290D)); + assertThat(loaded.floatVal, equalTo(390F)); + assertThat(loaded.intVal, equalTo(490)); + assertThat(loaded.longVal, equalTo(590L)); + assertThat(loaded.bigIntegerVal, equalTo(new BigInteger("690"))); + assertThat(loaded.bigDeciamVal, equalTo(new BigDecimal("790"))); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesBigNumberValueUsingStringComparisonWhenUsingMaxOperator() { + + TypeWithNumbers twn = new TypeWithNumbers(); + + // Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules. + // Therefore "80" is considered greater than "700" + twn.bigIntegerVal = new BigInteger("600"); + twn.bigDeciamVal = new BigDecimal("700.0"); + + template.save(twn); + + Update update = new Update()// + .max("bigIntegerVal", new BigInteger("70")) // + .max("bigDeciamVal", new BigDecimal("80")) // + ; + + template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class); + + TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0); + assertThat(loaded.bigIntegerVal, equalTo(new BigInteger("70"))); + assertThat(loaded.bigDeciamVal, equalTo(new BigDecimal("80"))); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void updatesBigNumberValueUsingStringComparisonWhenUsingMinOperator() { + + TypeWithNumbers twn = new TypeWithNumbers(); + + // Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules. + // Therefore "80" is considered greater than "700" + twn.bigIntegerVal = new BigInteger("80"); + twn.bigDeciamVal = new BigDecimal("90.0"); + + template.save(twn); + + Update update = new Update()// + .min("bigIntegerVal", new BigInteger("700")) // + .min("bigDeciamVal", new BigDecimal("800")) // + ; + + template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class); + + TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0); + assertThat(loaded.bigIntegerVal, equalTo(new BigInteger("700"))); + assertThat(loaded.bigDeciamVal, equalTo(new BigDecimal("800"))); + } + + static class TypeWithNumbers { + + @Id String id; + Integer intVal; + Float floatVal; + Long longVal; + Double doubleVal; + BigDecimal bigDeciamVal; + BigInteger bigIntegerVal; + Byte byteVal; + } + static class DoucmentWithNamedIdField { @Id String someIdKey; @@ -3215,11 +3407,11 @@ public class MongoTemplateTests { @Id public String id; - @Field("db_ref_list")/** @see DATAMONGO-1058 */ - @org.springframework.data.mongodb.core.mapping.DBRef// + @Field("db_ref_list") /** @see DATAMONGO-1058 */ + @org.springframework.data.mongodb.core.mapping.DBRef // public List dbRefAnnotatedList; - @org.springframework.data.mongodb.core.mapping.DBRef// + @org.springframework.data.mongodb.core.mapping.DBRef // public Sample dbRefProperty; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index feca9d76b..c27ac91b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2015 the original author or authors. + * Copyright 2013-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,10 +63,11 @@ import com.mongodb.DBRef; /** * Unit tests for {@link UpdateMapper}. - * + * * @author Oliver Gierke * @author Christoph Strobl * @author Thomas Darimont + * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) public class UpdateMapperUnitTests { @@ -687,10 +688,8 @@ public class UpdateMapperUnitTests { context.getPersistentEntity(DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes.class)); assertThat(mappedUpdate, isBsonObject().notContaining("$set.concreteTypeWithListAttributeOfInterfaceType._class")); - assertThat( - mappedUpdate, - isBsonObject().containing("$set.concreteTypeWithListAttributeOfInterfaceType.models.[0]._class", - ModelImpl.class.getName())); + assertThat(mappedUpdate, isBsonObject() + .containing("$set.concreteTypeWithListAttributeOfInterfaceType.models.[0]._class", ModelImpl.class.getName())); } /** @@ -757,8 +756,8 @@ public class UpdateMapperUnitTests { @Test public void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration() { - Map map = Collections. singletonMap("jasnah", new NestedDocument( - "kholin")); + Map map = Collections. singletonMap("jasnah", + new NestedDocument("kholin")); Update update = new Update().set("concreteMap", map); DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -887,6 +886,32 @@ public class UpdateMapperUnitTests { assertThat($set.get("primIntValue"), Is. is(10)); } + /** + * @see DATAMONGO-1404 + */ + @Test + public void mapsMinCorrectly() { + + Update update = new Update().min("minfield", 10); + DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(SimpleValueHolder.class)); + + assertThat(mappedUpdate, isBsonObject().containing("$min", new BasicDBObject("minfield", 10))); + } + + /** + * @see DATAMONGO-1404 + */ + @Test + public void mapsMaxCorrectly() { + + Update update = new Update().max("maxfield", 999); + DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(SimpleValueHolder.class)); + + assertThat(mappedUpdate, isBsonObject().containing("$max", new BasicDBObject("maxfield", 999))); + } + static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes { ListModelWrapper concreteTypeWithListAttributeOfInterfaceType; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java index d1c459110..47cc8fee9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 the original author or authors. + * Copyright 2010-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.Collections; +import java.util.Date; import java.util.Map; import org.joda.time.DateTime; @@ -31,12 +32,13 @@ import com.mongodb.DBObject; /** * Test cases for {@link Update}. - * + * * @author Oliver Gierke * @author Thomas Risberg * @author Becca Gaspard * @author Christoph Strobl * @author Thomas Darimont + * @author Alexey Plotnik */ public class UpdateTests { @@ -114,9 +116,8 @@ public class UpdateTests { Update u = new Update().pushAll("authors", new Object[] { m1, m2 }); u.pushAll("books", new Object[] { "Spring in Action" }); - assertThat( - u.getUpdateObject().toString(), - is("{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}] , \"books\" : [ \"Spring in Action\"]}}")); + assertThat(u.getUpdateObject().toString(), is( + "{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}] , \"books\" : [ \"Spring in Action\"]}}")); } @Test @@ -343,10 +344,11 @@ public class UpdateTests { .set("foo", "bar"); assertThat(actualUpdate.toString(), is(equalTo(expectedUpdate.toString()))); - assertThat(actualUpdate.toString(), is("{ \"$inc\" : { \"size\" : 1} ," // - + " \"$set\" : { \"nl\" : null , \"directory\" : \"/Users/Test/Desktop\" , \"foo\" : \"bar\"} , " // - + "\"$push\" : { \"authors\" : { \"name\" : \"Sven\"}} " // - + ", \"$pop\" : { \"authors\" : -1}}")); // + assertThat(actualUpdate.toString(), + is("{ \"$inc\" : { \"size\" : 1} ," // + + " \"$set\" : { \"nl\" : null , \"directory\" : \"/Users/Test/Desktop\" , \"foo\" : \"bar\"} , " // + + "\"$push\" : { \"authors\" : { \"name\" : \"Sven\"}} " // + + ", \"$pop\" : { \"authors\" : -1}}")); // } /** @@ -367,9 +369,8 @@ public class UpdateTests { public void getUpdateObjectShouldReturnCurrentDateCorrectlyForMultipleFieldsWhenUsingDate() { Update update = new Update().currentDate("foo").currentDate("bar"); - assertThat(update.getUpdateObject(), - equalTo(new BasicDBObjectBuilder().add("$currentDate", new BasicDBObject("foo", true).append("bar", true)) - .get())); + assertThat(update.getUpdateObject(), equalTo( + new BasicDBObjectBuilder().add("$currentDate", new BasicDBObject("foo", true).append("bar", true)).get())); } /** @@ -379,10 +380,8 @@ public class UpdateTests { public void getUpdateObjectShouldReturnCurrentDateCorrectlyForSingleFieldWhenUsingTimestamp() { Update update = new Update().currentTimestamp("foo"); - assertThat( - update.getUpdateObject(), - equalTo(new BasicDBObjectBuilder().add("$currentDate", - new BasicDBObject("foo", new BasicDBObject("$type", "timestamp"))).get())); + assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder() + .add("$currentDate", new BasicDBObject("foo", new BasicDBObject("$type", "timestamp"))).get())); } /** @@ -392,12 +391,11 @@ public class UpdateTests { public void getUpdateObjectShouldReturnCurrentDateCorrectlyForMultipleFieldsWhenUsingTimestamp() { Update update = new Update().currentTimestamp("foo").currentTimestamp("bar"); - assertThat( - update.getUpdateObject(), - equalTo(new BasicDBObjectBuilder().add( - "$currentDate", - new BasicDBObject("foo", new BasicDBObject("$type", "timestamp")).append("bar", new BasicDBObject("$type", - "timestamp"))).get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder() + .add("$currentDate", new BasicDBObject("foo", new BasicDBObject("$type", "timestamp")).append("bar", + new BasicDBObject("$type", "timestamp"))) + .get())); } /** @@ -407,10 +405,10 @@ public class UpdateTests { public void getUpdateObjectShouldReturnCurrentDateCorrectlyWhenUsingMixedDateAndTimestamp() { Update update = new Update().currentDate("foo").currentTimestamp("bar"); - assertThat( - update.getUpdateObject(), - equalTo(new BasicDBObjectBuilder().add("$currentDate", - new BasicDBObject("foo", true).append("bar", new BasicDBObject("$type", "timestamp"))).get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder() + .add("$currentDate", new BasicDBObject("foo", true).append("bar", new BasicDBObject("$type", "timestamp"))) + .get())); } /** @@ -439,8 +437,8 @@ public class UpdateTests { Update update = new Update().multiply("key", 10); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$mul", new BasicDBObject("key", 10D)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$mul", new BasicDBObject("key", 10D)).get())); } /** @@ -505,7 +503,6 @@ public class UpdateTests { assertThat(pullAll.get("field2"), is(notNullValue())); } - /** * @see DATAMONGO-1404 */ @@ -530,8 +527,8 @@ public class UpdateTests { Update update = new Update().max("key", 10); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", 10)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", 10)).get())); } /** @@ -542,8 +539,8 @@ public class UpdateTests { Update update = new Update().min("key", 10); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$min", new BasicDBObject("key", 10)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$min", new BasicDBObject("key", 10)).get())); } /** @@ -553,11 +550,10 @@ public class UpdateTests { public void shouldSuppressPreviousValueForMax() { Update update = new Update().max("key", 10); - update.max("key", 99); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", 99)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", 99)).get())); } /** @@ -567,11 +563,10 @@ public class UpdateTests { public void shouldSuppressPreviousValueForMin() { Update update = new Update().min("key", 10); + update.min("key", 99); - update.max("key", 99); - - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$min9", new BasicDBObject("key", 99)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$min", new BasicDBObject("key", 99)).get())); } /** @@ -580,12 +575,11 @@ public class UpdateTests { @Test public void getUpdateObjectShouldReturnCorrectDateRepresentationForMax() { - final java.util.Date date = new java.util.Date(); - + Date date = new Date(); Update update = new Update().max("key", date); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", date)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$max", new BasicDBObject("key", date)).get())); } /** @@ -594,11 +588,10 @@ public class UpdateTests { @Test public void getUpdateObjectShouldReturnCorrectDateRepresentationForMin() { - final java.util.Date date = new java.util.Date(); - + Date date = new Date(); Update update = new Update().min("key", date); - assertThat(update.getUpdateObject(), equalTo(new BasicDBObjectBuilder().add("$min", new BasicDBObject("key", date)) - .get())); + assertThat(update.getUpdateObject(), + equalTo(new BasicDBObjectBuilder().add("$min", new BasicDBObject("key", date)).get())); } } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 50df5db99..fe68c7bed 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,10 @@ [[new-features]] = New & Noteworthy +[[new-features.1-10-0]] +== What's new in Spring Data MongoDB 1.10 +* Support for `$min` and `$max` operators to `Update`. + [[new-features.1-9-0]] == What's new in Spring Data MongoDB 1.9 * The following annotations have been enabled to build own, composed annotations: `@Document`, `@Id`, `@Field`, `@Indexed`, `@CompoundIndex`, `@GeoSpatialIndexed`, `@TextIndexed`, `@Query`, `@Meta`. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 46b7a1ee1..71a2b5812 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -862,15 +862,21 @@ The Update class can be used with a little 'syntax sugar' as its methods are mea Here is a listing of methods on the Update class -* `Update` *addToSet* `(String key, Object value) ` Update using the `$addToSet` update modifier +* `Update` *addToSet* `(String key, Object value)` Update using the `$addToSet` update modifier +* `Update` *currentDate* `(String key)` Update using the `$currentDate` update modifier +* `Update` *currentTimestamp* `(String key)` Update using the `$currentDate` update modifier with `$type` `timestamp` * `Update` *inc* `(String key, Number inc)` Update using the `$inc` update modifier +* `Update` *max* `(String key, Object max)` Update using the `$max` update modifier +* `Update` *min* `(String key, Object min)` Update using the `$min` update modifier +* `Update` *multiply* `(String key, Number multiplier)` Update using the `$mul` update modifier * `Update` *pop* `(String key, Update.Position pos)` Update using the `$pop` update modifier * `Update` *pull* `(String key, Object value)` Update using the `$pull` update modifier * `Update` *pullAll* `(String key, Object[] values)` Update using the `$pullAll` update modifier -* `Update` *push* `(String key, Object value) ` Update using the `$push` update modifier +* `Update` *push* `(String key, Object value)` Update using the `$push` update modifier * `Update` *pushAll* `(String key, Object[] values)` Update using the `$pushAll` update modifier * `Update` *rename* `(String oldName, String newName)` Update using the `$rename` update modifier * `Update` *set* `(String key, Object value)` Update using the `$set` update modifier +* `Update` *setOnInsert* `(String key, Object value)` Update using the `$setOnInsert` update modifier * `Update` *unset* `(String key)` Update using the `$unset` update modifier [[mongo-template.upserts]]