介绍
有两种方法更新啦。第一种: insert/save 。第二种: update operation。
下面开始讨论。.
Updating (on the server)
当你调用update方法时,你其实就是发生一个修改命令给数据库。作用?当然是修改已存在的数据啦。
interface Datastore { ... /** updates all entities found with the operations*/ <T> UpdateResults<T> update(Query<T> query, UpdateOperations<T> ops); /** updates all entities found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/ <T> UpdateResults<T> update(Query<T> query, UpdateOperations<T> ops, boolean createIfMissing); /** updates the first entity found with the operations*/ <T> UpdateResults<T> updateFirst(Query<T> query, UpdateOperations<T> ops); /** updates the first entity found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/ <T> UpdateResults<T> updateFirst(Query<T> query, UpdateOperations<T> ops, boolean createIfMissing); /** updates the first entity found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/ <T> UpdateResults<T> updateFirst(Query<T> query, T entity, boolean createIfMissing); } public interface UpdateOperations<T> { /** sets the field value */ UpdateOperations<T> set(String fieldExpr, Object value); /** removes the field */ UpdateOperations<T> unset(String fieldExpr); /** adds the value to an array field*/ UpdateOperations<T> add(String fieldExpr, Object value); UpdateOperations<T> add(String fieldExpr, Object value, boolean addDups); /** adds the values to an array field*/ UpdateOperations<T> addAll(String fieldExpr, List<?> values, boolean addDups); /** removes the first value from the array*/ UpdateOperations<T> removeFirst(String fieldExpr); /** removes the last value from the array*/ UpdateOperations<T> removeLast(String fieldExpr); /** removes the value from the array field*/ UpdateOperations<T> removeAll(String fieldExpr, Object value); /** removes the values from the array field*/ UpdateOperations<T> removeAll(String fieldExpr, List<?> values); /** decrements the numeric field by 1*/ UpdateOperations<T> dec(String fieldExpr); /** increments the numeric field by 1*/ UpdateOperations<T> inc(String fieldExpr); /** increments the numeric field by value (negatives are allowed)*/ UpdateOperations<T> inc(String fieldExpr, Number value); }
The Field Expression
属性表达式可以作用于所有的操作。可以是一个的属性,也可以是点嵌套的属性。你也可以使用 ($)在属性表达式中。
Samples initialization
Morphia morphia = new Morphia(); morphia.map(Hotel.class).map(Address.class); Datastore datastore = morphia.createDatastore("MorphiaSampleDb"); Hotel hotel = new Hotel("Fairmont", 3, new Address("1 Rideau Street", "Ottawa", "K1N8S7", "Canada")); datastore.save(hotel); UpdateOperations<Hotel> ops; // This query will be used in the samples to restrict the update operations to only the hotel we just created. // If this was not supplied, by default the update() operates on all documents in the collection. // We could use any field here but _id will be unique and mongodb by default puts an index on the _id field so this should be fast! Query<Hotel> updateQuery = datastore.createQuery(Hotel.class).field("_id").equal(hotel.getId()); // The Mapper class also provides a public static of the default _id field name for us... Query<Hotel> updateQuery = datastore.createQuery(Hotel.class).field(Mapper.ID_KEY).equal(hotel.getId());
注意:使用的是 equal(),而不是 equals()
@Entity("hotels") public class Hotel { @Id private ObjectId id; private String name; private int stars; @Embedded private Address address; @Embedded List<Integer> roomNumbers = new ArrayList<Integer>(); // ... getters and setters } @Embedded public class Address { private String street; private String city; private String postalCode; private String country; // ... getters and setters }
set/unset
// change the name of the hotel ops = datastore.createUpdateOperations(Hotel.class).set("name", "Fairmont Chateau Laurier"); datastore.update(updateQuery, ops); // also works for embedded documents, change the name of the city in the address ops = datastore.createUpdateOperations(Hotel.class).set("address.city", "Ottawa"); datastore.update(updateQuery, ops); // remove the name property from the document // causes the next load of the Hotel to have name = null ops = datastore.createUpdateOperations(Hotel.class).unset("name"); datastore.update(updateQuery, ops);
inc/dec
// increment 'stars' by 1 ops = datastore.createUpdateOperations(Hotel.class).inc("stars"); datastore.update(updateQuery, ops); // increment 'stars' by 4 ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 4); datastore.update(updateQuery, ops); // decrement 'stars' by 1 ops = datastore.createUpdateOperations(Hotel.class).dec("stars"); // same as .inc("stars", -1) datastore.update(updateQuery, ops); // decrement 'stars' by 4 ops = datastore.createUpdateOperations(Hotel.class).inc("stars", -4); datastore.update(updateQuery, ops);
add/All
// push a value onto an array() (+v 0.95) // same as .add("roomNumbers", 11, false) ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11); datastore.update(updateQuery, ops); // [ 11 ]
当你向一个不是数组的属性,进行数组的操作。会报错的。
ops = datastore.createUpdateOperations(Hotel.class).set("roomNumbers", 11); datastore.update(updateQuery, ops); // causes error since 'roomNumbers' is not an array at this point ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false); datastore.update(updateQuery, ops); // causes error // delete the property ops = datastore.createUpdateOperations(Hotel.class).unset("roomNumbers"); datastore.update(updateQuery, ops); // use the 3rd parameter to add duplicates // add to end of array, same as add() ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false); datastore.update(updateQuery, ops); // [ 11 ] // no change since its a duplicate... doesn't cause error ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false); datastore.update(updateQuery, ops); // [ 11 ] // push onto the end of the array ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 12, false); datastore.update(updateQuery, ops); // [ 11, 12 ] // add even if its a duplicate ops = datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, true); datastore.update(updateQuery, ops); // [ 11, 12, 11 ]
removeFirst/Last/All
//given roomNumbers = [ 1, 2, 3 ] ops = datastore.createUpdateOperations(Hotel.class).removeFirst("roomNumbers"); datastore.update(updateQuery, ops); // [ 2, 3 ] //given roomNumbers = [ 1, 2, 3 ] ops = datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers"); datastore.update(updateQuery, ops); // [ 1, 2 ] ops = datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers"); datastore.update(updateQuery, ops); // [ 1 ] ops = datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers"); datastore.update(updateQuery, ops); // [] empty array //given roomNumbers = [ 1, 2, 3, 3 ] ops = datastore.createUpdateOperations(Hotel.class).removeAll("roomNumbers", 3); datastore.update(updateQuery, ops); // [ 1, 2 ] //given roomNumbers = [ 1, 2, 3, 3 ] ops = datastore.createUpdateOperations(Hotel.class).removeAll("roomNumbers", Arrays.asList(2, 3)); datastore.update(updateQuery, ops); // [ 1 ]
Multiple Operations
你也可以在一个operation里面做多个操作。
//set city to Ottawa and increment stars by 1 ops = datastore.createUpdateOperations(Hotel.class).set("city", "Ottawa").inc("stars"); datastore.update(updateQuery, ops); //if you perform multiple operations in one command on the same property, results will vary ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50).inc("stars"); //increments by 1 ops = datastore.createUpdateOperations(Hotel.class).inc("stars").inc("stars", 50); //increments by 50 //you can't apply conflicting operations to the same property ops = datastore.createUpdateOperations(Hotel.class).set("stars", 1).inc("stars", 50); //causes error
updateFirst method
In the default driver and shell this is the default behavior. In Morphia we feel like updating all the results of the query is a better default (see below).
{ name: "Fairmont", stars: 5}, { name: "Last Chance", stars: 3 }
ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50); // (+v 0.95 now takes into account the order()) // morphia exposes a specific updateFirst to update only the first hotel matching the query datastore.updateFirst(datastore.find(Hotel.class).order("stars"), ops); // update only Last Chance datastore.updateFirst(datastore.find(Hotel.class).order("-stars"), ops); // update only Fairmont
//default shell version is to match first //shell version has a multi to indicate to update all matches, not just first //to mimic morphia operation, set multi = false db.collection.update( criteria, objNew, upsert, multi );
update method
ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50); // morphia default update is to update all the hotels datastore.update(datastore.createQuery(Hotel.class), ops); //increments all hotels
//equivalent morphia shell version is... upsert = false, multi = true db.collection.update( criteria, objNew, false, true );
createIfMissing (overload parameter)
all of the update methods are overloaded and accept a "createIfMissing" parameter
ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50); //update, if not found create it datastore.updateFirst(datastore.createQuery(Hotel.class).field("stars").greaterThan(100), ops, true); // creates { "_id" : ObjectId("4c60629d2f1200000000161d"), "stars" : 50 }
//equivalent morphia shell version is... upsert = true db.collection.update( criteria, objNew, true, multi );