package org.mongodb.morphia;
import org.bson.types.ObjectId;
import org.junit.Assert;
import org.junit.Test;
import org.mongodb.morphia.annotations.Embedded;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Property;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonMap;
public class TestArrayUpdates extends TestBase {
@Test
public void testStudents() {
getMorphia().map(Student.class);
final Datastore datastore = getDs();
datastore.ensureIndexes();
datastore.save(new Student(1L, new Grade(80, singletonMap("name", "Homework")),
new Grade(90, singletonMap("name", "Test"))));
Query<Student> testQuery = datastore.find(Student.class)
.field("_id").equal(1L)
.field("grades.data.name").equal("Test");
Assert.assertNotNull(testQuery.get());
UpdateOperations<Student> operations = datastore.createUpdateOperations(Student.class);
operations.set("grades.$.data.name", "Makeup Test");
datastore.update(testQuery, operations);
Assert.assertNull(testQuery.get());
Assert.assertNotNull(datastore.find(Student.class)
.field("_id").equal(1L)
.field("grades.data.name").equal("Makeup Test")
.get());
}
@Test
public void testUpdatesWithArrayIndexPosition() {
getMorphia().map(Student.class);
final Datastore datastore = getDs();
datastore.ensureIndexes();
datastore.save(new Student(1L, new Grade(80, singletonMap("name", "Homework")),
new Grade(90, singletonMap("name", "Test"))));
Query<Student> testQuery = datastore.find(Student.class)
.field("_id").equal(1L)
.field("grades.data.name").equal("Test");
Assert.assertNotNull(testQuery.get());
// Update the second element. Array indexes are zero-based.
UpdateOperations<Student> operations = datastore.createUpdateOperations(Student.class);
operations.set("grades.1.data.name", "Makeup Test");
datastore.update(testQuery, operations);
Assert.assertNull(testQuery.get());
Assert.assertNotNull(datastore.find(Student.class)
.field("_id").equal(1L)
.field("grades.data.name").equal("Makeup Test")
.get());
}
@Test
public void testUpdates() {
BatchData theBatch = new BatchData();
theBatch.files.add(new Files(0, "fileName1", "fileHash1"));
theBatch.files.add(new Files(0, "fileName2", "fileHash2"));
getDs().save(theBatch);
ObjectId id = theBatch.id;
theBatch = new BatchData();
theBatch.files.add(new Files(0, "fileName3", "fileHash3"));
theBatch.files.add(new Files(0, "fileName4", "fileHash4"));
getDs().save(theBatch);
ObjectId id2 = theBatch.id;
UpdateOperations<BatchData> updateOperations = getDs().createUpdateOperations(BatchData.class)
.set("files.$.fileHash", "new hash");
getDs().update(getDs().find(BatchData.class)
.filter("_id", id)
.filter("files.fileName", "fileName1"),
updateOperations);
BatchData data = getDs().find(BatchData.class)
.filter("_id", id)
.get();
Assert.assertEquals("new hash", data.files.get(0).fileHash);
Assert.assertEquals("fileHash2", data.files.get(1).fileHash);
data = getDs().find(BatchData.class)
.filter("_id", id2)
.get();
Assert.assertEquals("fileHash3", data.files.get(0).fileHash);
Assert.assertEquals("fileHash4", data.files.get(1).fileHash);
}
@Entity
public static class BatchData {
@Id
private ObjectId id;
@Embedded
private List<Files> files = new ArrayList<Files>();
@Override
public String toString() {
return format("BatchData{id=%s, files=%s}", id, files);
}
}
@Embedded
public static class Files {
private int position;
private String fileName = "";
private String fileHash = "";
public Files() {
}
public Files(final int pos, final String fileName, final String fileHash) {
this.position = pos;
this.fileName = fileName;
this.fileHash = fileHash;
}
@Override
public String toString() {
return format("Files{fileHash='%s', fileName='%s', position=%d}", fileHash, fileName, position);
}
}
@Entity
public static class Student {
@Id
private long id;
private List<Grade> grades;
public Student() {
}
public Student(final long id, final Grade... grades) {
this.id = id;
this.grades = asList(grades);
}
@Override
public String toString() {
return ("id: " + id + ", grades: " + grades);
}
}
@Embedded
public static class Grade {
private int marks;
@Property("d")
private Map<String, String> data;
public Grade() {
}
public Grade(final int marks, final Map<String, String> data) {
this.marks = marks;
this.data = data;
}
@Override
public String toString() {
return ("marks: " + marks + ", data: " + data);
}
}
}