Skip to content

Commit dab6034

Browse files
christophstroblThomas Darimont
authored andcommitted
DATAMONGO-943 - Add support for $position to Update $push $each.
We now support $position on update.push. Original pull request: #248.
1 parent 461e7d0 commit dab6034

File tree

3 files changed

+142
-1
lines changed

3 files changed

+142
-1
lines changed

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ public Update push(String key, Object value) {
163163

164164
/**
165165
* Update using {@code $push} modifier. <br/>
166-
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values.
166+
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values as well as using
167+
* {@code $position}.
167168
*
168169
* @see http://docs.mongodb.org/manual/reference/operator/update/push/
169170
* @see http://docs.mongodb.org/manual/reference/operator/update/each/
@@ -577,6 +578,31 @@ public boolean equals(Object that) {
577578
}
578579
}
579580

581+
/**
582+
* {@link Modifier} implementation used to propagate {@code $position}.
583+
*
584+
* @author Christoph Strobl
585+
* @since 1.7
586+
*/
587+
private static class PositionModifier implements Modifier {
588+
589+
private final int position;
590+
591+
public PositionModifier(int position) {
592+
this.position = position;
593+
}
594+
595+
@Override
596+
public String getKey() {
597+
return "$position";
598+
}
599+
600+
@Override
601+
public Object getValue() {
602+
return position;
603+
}
604+
}
605+
580606
/**
581607
* Builder for creating {@code $push} modifiers
582608
*
@@ -605,6 +631,42 @@ public Update each(Object... values) {
605631
return Update.this.push(key, this.modifiers);
606632
}
607633

634+
/**
635+
* Forces values to be added at the given {@literal position}.
636+
*
637+
* @param position needs to be greater than or equal to zero.
638+
* @return
639+
* @since 1.7
640+
*/
641+
public PushOperatorBuilder atPosition(int position) {
642+
643+
if (position < 0) {
644+
throw new IllegalArgumentException("Position must be greater than or equal to zero.");
645+
}
646+
647+
this.modifiers.addModifier(new PositionModifier(position));
648+
649+
return this;
650+
}
651+
652+
/**
653+
* Forces values to be added at given {@literal position}.
654+
*
655+
* @param position can be {@literal null} which will be appended at the last position.
656+
* @return
657+
* @since 1.7
658+
*/
659+
public PushOperatorBuilder atPosition(Position position) {
660+
661+
if (position == null || Position.LAST.equals(position)) {
662+
return this;
663+
}
664+
665+
this.modifiers.addModifier(new PositionModifier(0));
666+
667+
return this;
668+
}
669+
608670
/**
609671
* Propagates {@link #value(Object)} to {@code $push}
610672
*

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.springframework.data.mongodb.core.query.Criteria;
4545
import org.springframework.data.mongodb.core.query.Query;
4646
import org.springframework.data.mongodb.core.query.Update;
47+
import org.springframework.data.mongodb.core.query.Update.Position;
4748

4849
import com.mongodb.BasicDBList;
4950
import com.mongodb.BasicDBObject;
@@ -293,6 +294,76 @@ public void testUpdateShouldAllowMultiplePushEachForDifferentFields() {
293294
assertThat(getAsDBObject(push, "type").containsField("$each"), is(true));
294295
}
295296

297+
/**
298+
* @see DATAMONGO-943
299+
*/
300+
@Test
301+
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositiveIndexParameter() {
302+
303+
Update update = new Update().push("key").atPosition(2).each(Arrays.asList("Arya", "Arry", "Weasel"));
304+
305+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));
306+
307+
DBObject push = getAsDBObject(mappedObject, "$push");
308+
DBObject key = getAsDBObject(push, "key");
309+
310+
assertThat(key.containsField("$position"), is(true));
311+
assertThat((Integer) key.get("$position"), is(2));
312+
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
313+
}
314+
315+
/**
316+
* @see DATAMONGO-943
317+
*/
318+
@Test
319+
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionFirst() {
320+
321+
Update update = new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel"));
322+
323+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));
324+
325+
DBObject push = getAsDBObject(mappedObject, "$push");
326+
DBObject key = getAsDBObject(push, "key");
327+
328+
assertThat(key.containsField("$position"), is(true));
329+
assertThat((Integer) key.get("$position"), is(0));
330+
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
331+
}
332+
333+
/**
334+
* @see DATAMONGO-943
335+
*/
336+
@Test
337+
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionLast() {
338+
339+
Update update = new Update().push("key").atPosition(Position.LAST).each(Arrays.asList("Arya", "Arry", "Weasel"));
340+
341+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));
342+
343+
DBObject push = getAsDBObject(mappedObject, "$push");
344+
DBObject key = getAsDBObject(push, "key");
345+
346+
assertThat(key.containsField("$position"), is(false));
347+
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
348+
}
349+
350+
/**
351+
* @see DATAMONGO-943
352+
*/
353+
@Test
354+
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionNull() {
355+
356+
Update update = new Update().push("key").atPosition(null).each(Arrays.asList("Arya", "Arry", "Weasel"));
357+
358+
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));
359+
360+
DBObject push = getAsDBObject(mappedObject, "$push");
361+
DBObject key = getAsDBObject(push, "key");
362+
363+
assertThat(key.containsField("$position"), is(false));
364+
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
365+
}
366+
296367
/**
297368
* @see DATAMONGO-410
298369
*/

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,4 +476,12 @@ public void getUpdateObjectShouldReturnCorrectRepresentationForBitwiseXor() {
476476
assertThat(update.getUpdateObject(),
477477
equalTo(new BasicDBObjectBuilder().add("$bit", new BasicDBObject("key", new BasicDBObject("xor", 10L))).get()));
478478
}
479+
480+
/**
481+
* @see DATAMONGO-943
482+
*/
483+
@Test(expected = IllegalArgumentException.class)
484+
public void pushShouldThrowExceptionWhenGivenNegativePosition() {
485+
new Update().push("foo").atPosition(-1).each("booh");
486+
}
479487
}

0 commit comments

Comments
 (0)