Push an Object into an array (
addToSet)
Si trabajáis con MongoDB ya sabréis que podemos utilizar el comando push para introducir valores en un arrary.
Por ejemplo si tenemos el siguiente objecto mapeado en MongoDB
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import com.google.code.morphia.annotations.Entity;
@Entity
@Document
public class Course implements Serializable {
private static final long serialVersionUID = -7251789829032925885L;
@Id
private String id = UUID.randomUUID().toString();
private String name;
private String description;
private long creationDate = new Date().getTime();
private int duration;
private int credits;
private List<String> tags = new ArrayList<String>();
private List<String> users = new ArrayList<User>();
Si queremos introducir un valor String en el array de tags es tan fácil como hace esto
public void addTag(String courseId, String tag){
WriteResult wr = mongoOperations.updateFirst(
new Query(where("id").is(courseId)),
new Update().push("tags", tag),Course.class);
}
El resultado en MongoDb debería ser algo parecido a esto
{"_class": "com.antuansoft.Course",
"_id": "953a878e-5aa6-4811-82e3-660b00ebafe2",
"creationDate": 1344439353237,
"credits": 10,
"description": "Course DESCRIPTION",
"duration": 100,
"name": "Course 1",
"tags": {
"0": "tag1"
"1": "tag2"
}}
Al insertar en el array de tags objetos de la clase String no hay ningún problema ya que los entiende perfectamente.
El problema que he encontrado ocurre cuando tienes que insertar en el array Objectos de alguna clase que no sean tipos básicos. Por ejemplo un objecto de la clase User.
El problema que ocurre es que al insertarlo de la misma manera que un String normal no transforma el objeto y no pone las propiedades ni "_id" ni "_class", o sea que no lo transforma e introduce sólo las propiedades que tenga ese objeto en el array.
Para solucionar esto utilizamos una par de instrucciones que fuerzan a MongoDb a realizar esta transformación.
DBObject dbo = new BasicDBObject();
mongoOperations.getConverter().write(user, dbo);
public void addUser(String idCourse, User user){
DBObject dbo = new BasicDBObject();
mongoOperations.getConverter().write(user, dbo);
WriteResult wr = mongoOperations.updateFirst(
new Query(where("id").is(idCourse)),
new Update().push("users", dbo),Course.class);
{"_class": "com.antuansoft.Course",
"_id": "953a878e-5aa6-4811-82e3-660b00ebafe2",
"creationDate": 1344439353237,
"credits": 10,
"description": "Course DESCRIPTION",
"duration": 100,
"name": "Course 1",
"tags": {
"0": "tag1"
"1": "tag2"
}
"users": {
"0": {
"_class": "com.antuansoft.User",
"_id": "047cd911-356a-4851-948a-3087ea735353",
"name": "AntuanSoft"
}
}
}
Nota: Si no queremos que aparezcan valores repetidos en nuestra lista de objetos/strings lo mejor es utilizar el método
addToSet en vez de push. De este modo si introducimos un valor que ya existe, este no se insetará