Skip to content

Commit 5e43f58

Browse files
christophstroblodrotbohm
authored andcommitted
DATAMONGO-471 - Add support for $each when using $addToSet.
Additionally to Update.addToSet(String, Object) the method 'addToSet(String)' has been introduced, returning a builder to allow the creation of $addToSet command for either single value, or multiple values using $each. Using value: new Update().addToSet("key").value("spring"); Using each: new Update().addToSet("key").each("spring", "data", "mongodb"); Original Pull Request: spring-projects#157.
1 parent 2cfd478 commit 5e43f58

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ public Update pushAll(String key, Object[] values) {
196196
return this;
197197
}
198198

199+
/**
200+
* Update using {@code $addToSet} modifier. <br/>
201+
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values
202+
*
203+
* @param key
204+
* @return
205+
* @since 1.5
206+
*/
207+
public AddToSetBuilder addToSet(String key) {
208+
return new AddToSetBuilder(key);
209+
}
210+
199211
/**
200212
* Update using the {@literal $addToSet} update modifier
201213
*
@@ -408,7 +420,7 @@ public Object getValue() {
408420
/**
409421
* Builder for creating {@code $push} modifiers
410422
*
411-
* @author Christop Strobl
423+
* @author Christoph Strobl
412424
*/
413425
public class PushOperatorBuilder {
414426

@@ -442,4 +454,41 @@ public Update value(Object value) {
442454
return Update.this.push(key, value);
443455
}
444456
}
457+
458+
/**
459+
* Builder for creating {@code $addToSet} modifier.
460+
*
461+
* @author Christoph Strobl
462+
* @since 1.5
463+
*/
464+
public class AddToSetBuilder {
465+
466+
private final String key;
467+
468+
public AddToSetBuilder(String key) {
469+
this.key = key;
470+
}
471+
472+
/**
473+
* Propagates {@code $each} to {@code $addToSet}
474+
*
475+
* @param values
476+
* @return
477+
*/
478+
public Update each(Object... values) {
479+
return Update.this.addToSet(this.key, new Each(values));
480+
}
481+
482+
/**
483+
* Propagates {@link #value(Object)} to {@code $addToSet}
484+
*
485+
* @param values
486+
* @return
487+
*/
488+
public Update value(Object value) {
489+
return Update.this.addToSet(this.key, value);
490+
}
491+
492+
}
493+
445494
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,25 @@ public void callingNonObjectMethodsOnLazyLoadingProxyShouldReturnNullIfUnderlyin
25802580
assertThat(savedTmpl.getContent().getText(), is(nullValue()));
25812581
}
25822582

2583+
/**
2584+
* @see DATAMONGO-471
2585+
*/
2586+
@Test
2587+
public void updateMultiShouldAddValuesCorrectlyWhenUsingAddToSetWithEach() {
2588+
2589+
DocumentWithCollectionOfSimpleType document = new DocumentWithCollectionOfSimpleType();
2590+
document.values = Arrays.asList("spring");
2591+
template.save(document);
2592+
2593+
Query query = query(where("id").is(document.id));
2594+
assumeThat(template.findOne(query, DocumentWithCollectionOfSimpleType.class).values, hasSize(1));
2595+
2596+
Update update = new Update().addToSet("values").each("data", "mongodb");
2597+
template.updateMulti(query, update, DocumentWithCollectionOfSimpleType.class);
2598+
2599+
assertThat(template.findOne(query, DocumentWithCollectionOfSimpleType.class).values, hasSize(3));
2600+
}
2601+
25832602
static class DocumentWithDBRefCollection {
25842603

25852604
@Id public String id;

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,46 @@ public void doesNotConvertRawDbObjects() {
412412
assertThat(inClause, IsIterableContainingInOrder.<Object> contains(1L, 2L));
413413
}
414414

415+
/**
416+
* @see DATAMONG0-471
417+
*/
418+
@SuppressWarnings({ "unchecked", "rawtypes" })
419+
@Test
420+
public void testUpdateShouldApply$addToSetCorrectlyWhenUsedWith$each() {
421+
422+
Update update = new Update().addToSet("values").each("spring", "data", "mongodb");
423+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
424+
context.getPersistentEntity(ListModel.class));
425+
426+
DBObject addToSet = getAsDBObject(mappedObject, "$addToSet");
427+
DBObject values = getAsDBObject(addToSet, "values");
428+
BasicDBList each = getAsDBList(values, "$each");
429+
430+
assertThat(each.toMap(), (Matcher) allOf(hasValue("spring"), hasValue("data"), hasValue("mongodb")));
431+
}
432+
433+
/**
434+
* @see DATAMONG0-471
435+
*/
436+
@Test
437+
public void testUpdateShouldRetainClassTypeInformationWhenUsing$addToSetWith$eachForCustomTypes() {
438+
439+
Update update = new Update().addToSet("models").each(new ModelImpl(2014), new ModelImpl(1), new ModelImpl(28));
440+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
441+
context.getPersistentEntity(ModelWrapper.class));
442+
443+
DBObject addToSet = getAsDBObject(mappedObject, "$addToSet");
444+
445+
DBObject values = getAsDBObject(addToSet, "models");
446+
BasicDBList each = getAsDBList(values, "$each");
447+
448+
for (Object updateValue : each) {
449+
assertThat(((DBObject) updateValue).get("_class").toString(),
450+
equalTo("org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests$ModelImpl"));
451+
}
452+
453+
}
454+
415455
static interface Model {}
416456

417457
static class ModelImpl implements Model {
@@ -425,6 +465,12 @@ public ModelImpl(int value) {
425465

426466
public class ModelWrapper {
427467
Model model;
468+
469+
public ModelWrapper() {}
470+
471+
public ModelWrapper(Model model) {
472+
this.model = model;
473+
}
428474
}
429475

430476
static class ListModelWrapper {

0 commit comments

Comments
 (0)