原標(biāo)題:Spring Data MongoDB參考文檔三(內(nèi)容來源:Spring中國教育管理中心) 自定義類型映射如果你不想把整個Java類名寫成類型信息,而是想用一個key,你可以@TypeAlias在實體類上使用注解。如果你需要更多的自定義映射,看看TypeInformationMapper接口。該接口的實例可以在 上配置DefaultMongoTypeMapper,而后者又可以在 上配置MappingMongoConverter。以下示例顯示了如何為實體定義類型別名: 示例 64.為實體定義類型別名 @TypeAlias("pers")class Person { } 請注意,生成的文檔包含字段中pers的值_class。 類型別名僅在映射上下文知道實際類型時才有效。所需的實體元數(shù)據(jù)在第一次保存時確定,或者必須通過配置初始實體集提供。默認(rèn)情況下,配置類會掃描基礎(chǔ)包以尋找潛在的候選者。 @Configuration public class AppConfig extends AbstractMongoClientConfiguration { @Override protected Set<Class<?>> getInitialEntitySet() { return Collections.singleton(Person.class); } // ... } 配置自定義類型映射下面的例子說明如何配置自定義MongoTypeMapper的MappingMongoConverter: 示例 65.MongoTypeMapper使用 Spring Java Config配置自定義 class CustomMongoTypeMapper extends DefaultMongoTypeMapper { //implement custom type mapping here} @Configurationclass SampleMongoConfiguration extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { return "database"; } @Bean @Override public MappingMongoConverter mappingMongoConverter() throws Exception { MappingMongoConverter mmc = super.mappingMongoConverter(); mmc.setTypeMapper(customTypeMapper()); return mmc; } @Bean public MongoTypeMapper customTypeMapper() { return new CustomMongoTypeMapper(); } } 請注意,前面的示例擴展了 以下示例顯示如何使用 XML 配置自定義MongoTypeMapper: 示例 66.MongoTypeMapper使用 XML配置自定義 <mongo:mapping-converter type-mapper-ref="customMongoTypeMapper"/> <bean name="customMongoTypeMapper" class="com.bubu.mongo.CustomMongoTypeMapper"/> 11.5.3.保存和插入文檔的方法有幾種方便的方法可MongoTemplate用于保存和插入對象。要對轉(zhuǎn)換過程進行更細(xì)粒度的控制,您可以使用MappingMongoConverter?- 例如Converter<Person, Document>和注冊 Spring 轉(zhuǎn)換器Converter<Document, Person>。 插入和保存操作之間的區(qū)別在于,如果對象尚不存在,則保存操作會執(zhí)行插入操作。 使用保存操作的簡單情況是保存一個 POJO。在這種情況下,集合名稱由類的名稱(非完全限定)確定。您還可以使用特定的集合名稱調(diào)用保存操作。您可以使用映射元數(shù)據(jù)來覆蓋存儲對象的集合。 插入或保存時,如果Id未設(shè)置該屬性,則假設(shè)其值將由數(shù)據(jù)庫自動生成。因此,ObjectId要成功自動生成 an ,類中的Id屬性或字段的類型必須是 a String、 anObjectId或 a BigInteger。 以下示例顯示了如何保存文檔并檢索其內(nèi)容: 示例 67. 使用 MongoTemplate 插入和檢索文檔 import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Criteria.query; … Person p = new Person("Bob", 33); mongoTemplate.insert(p); Person qp = mongoTemplate.findOne(query(where("age").is(33)), Person.class); 以下插入和保存操作可用:
也可以使用一組類似的插入操作:
我的文檔保存在哪個集合中?有兩種方法可以管理用于文檔的集合名稱。使用的默認(rèn)集合名稱是更改為以小寫字母開頭的類名稱。所以一個com.test.Person類存儲在person集合中。您可以通過為@Document注釋提供不同的集合名稱來對此進行自定義。您還可以通過提供您自己的集合名稱作為所選MongoTemplate方法調(diào)用的最后一個參數(shù)來覆蓋集合名稱。 插入或保存單個對象MongoDB 驅(qū)動程序支持在單個操作中插入文檔集合。MongoOperations接口中的以下方法支持此功能:
批量插入多個對象MongoDB 驅(qū)動程序支持在一個操作中插入一組文檔。MongoOperations接口中的以下方法支持此功能:
11.5.4.更新集合中的文檔對于更新,您可以使用 using 更新找到的第一個文檔,也可以使用 示例 68. 使用 MongoTemplate import static org.springframework.data.mongodb.core.query.Criteria.where;import static org.springframework.data.mongodb.core.query.Query;import static org.springframework.data.mongodb.core.query.Update; ... WriteResult wr = mongoTemplate.updateMulti(new Query(where("accounts.accountType").is(Account.Type.SAVINGS)), new Update().inc("accounts.$.balance", 50.00), Account.class); 除了Query前面討論的之外,我們還通過使用Update對象來提供更新定義。該Update班有匹配供MongoDB的更新改進劑的方法。 大多數(shù)方法都會返回Update對象,為 API 提供流暢的樣式。 運行文檔更新的方法
updateFirst不支持訂購。請使用findAndModify申請Sort。 Update類中的方法您可以在類中使用一點“'語法糖'” Update,因為它的方法旨在鏈接在一起。此外,您可以Update通過public static Update update(String key, Object value)使用靜態(tài)導(dǎo)入來啟動新實例的創(chuàng)建。 本Update類包含以下方法:
一些更新修飾符,例如$pushand $addToSet,允許嵌套額外的運算符。 // { $push : { "category" : { "$each" : [ "spring" , "data" ] } } } new Update().push("category").each("spring", "data") // { $push : { "key" : { "$position" : 0 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } } new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel")); // { $push : { "key" : { "$slice" : 5 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } } new Update().push("key").slice(5).each(Arrays.asList("Arya", "Arry", "Weasel")); // { $addToSet : { "values" : { "$each" : [ "spring" , "data" , "mongodb" ] } } } new Update().addToSet("values").each("spring", "data", "mongodb"); 11.5.5.“更新”集合中的文檔與執(zhí)行updateFirst操作相關(guān),您還可以執(zhí)行“upsert”操作,如果找不到與查詢匹配的文檔,它將執(zhí)行插入操作。插入的文檔是查詢文檔和更新文檔的組合。以下示例顯示了如何使用該upsert方法: template.update(Person.class) .matching(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")) .apply(update("address", addr)) .upsert(); upsert不支持訂購。請使用findAndModify申請Sort。 11.5.6.在集合中查找和更新文檔該findAndModify(…)對方法MongoCollection可以更新的文件,并在單個操作中返回老任或新更新的文件。MongoTemplate提供了四個findAndModify重載方法,它們接受Query和Update類并將 from 轉(zhuǎn)換Document為您的 POJO: <T> T findAndModify(Query query, Update update, Class<T> entityClass);<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass, String collectionName); 以下示例將一些Person對象插入容器并執(zhí)行findAndUpdate操作: template.insert(new Person("Tom", 21)); template.insert(new Person("Dick", 22)); template.insert(new Person("Harry", 23)); Query query = new Query(Criteria.where("firstName").is("Harry"));Update update = new Update().inc("age", 1); Person oldValue = template.update(Person.class) .matching(query) .apply(update) .findAndModifyValue(); // return's old person object assertThat(oldValue.getFirstName()).isEqualTo("Harry"); assertThat(oldValue.getAge()).isEqualTo(23); Person newValue = template.query(Person.class) .matching(query) .findOneValue(); assertThat(newValue.getAge()).isEqualTo(24); Person newestValue = template.update(Person.class) .matching(query) .apply(update) .withOptions(FindAndModifyOptions.options().returnNew(true)) // Now return the newly updated document when updating .findAndModifyValue(); assertThat(newestValue.getAge()).isEqualTo(25); 該FindAndModifyOptions方法可以讓你設(shè)置的選項returnNew,upsert以及remove從前面的代碼片段延伸.An例子如下: Person upserted = template.update(Person.class) .matching(new Query(Criteria.where("firstName").is("Mary"))) .apply(update) .withOptions(FindAndModifyOptions.options().upsert(true).returnNew(true)) .findAndModifyValue() assertThat(upserted.getFirstName()).isEqualTo("Mary"); assertThat(upserted.getAge()).isOne(); 11.5.7.聚合管道更新更新方法公開MongoOperations并通過聚合管道ReactiveMongoOperations接受聚合管道AggregationUpdate。UsingAggregationUpdate允許在更新操作中利用MongoDB 4.2 聚合。在更新中使用聚合允許通過使用單個操作表達多個階段和多個條件來更新一個或多個字段。 更新可以包括以下階段:
示例 69. 更新聚合 AggregationUpdate update = Aggregation.newUpdate() .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) .set("grade").toValue(ConditionalOperators.switchCases( when(valueOf("average").greaterThanEqualToValue(90)).then("A"), when(valueOf("average").greaterThanEqualToValue(80)).then("B"), when(valueOf("average").greaterThanEqualToValue(70)).then("C"), when(valueOf("average").greaterThanEqualToValue(60)).then("D")) .defaultTo("F") ); template.update(Student.class) .apply(update) .all(); db.students.update( { }, [ { $set: { average : { $avg: "$tests" } } }, { $set: { grade: { $switch: { branches: [ { case: { $gte: [ "$average", 90 ] }, then: "A" }, { case: { $gte: [ "$average", 80 ] }, then: "B" }, { case: { $gte: [ "$average", 70 ] }, then: "C" }, { case: { $gte: [ "$average", 60 ] }, then: "D" } ], default: "F" } } } } ], { multi: true } ) 第一$set階段根據(jù)測試字段的平均值計算新的字段平均值。 第二$set階段根據(jù)第一聚合階段計算的平均字段計算新的字段等級。 管道在學(xué)生集合上運行并Student用于聚合字段映射。 將更新應(yīng)用于集合中的所有匹配文檔。 11.5.8.查找和替換文檔替換整個的最直接的方法Document是通過它idusingsave方法。然而,這可能并不總是可行的。findAndReplace提供了一種替代方法,允許通過簡單的查詢來識別要替換的文檔。 示例 70. 查找和替換文檔 Optional<User> result = template.update(Person.class) .matching(query(where("firstame").is("Tom"))) .replaceWith(new Person("Dick")) .withOptions(FindAndReplaceOptions.options().upsert()) .as(User.class) .findAndReplace(); 使用具有給定域類型的 fluent update API 來映射查詢和派生集合名稱,或者僅使用MongoOperations#findAndReplace. 映射到給定域類型的實際匹配查詢。通過查詢提供sort,fields和collation設(shè)置。 額外的可選鉤子以提供默認(rèn)值以外的選項,如upsert. 用于映射運算結(jié)果的可選投影類型。如果沒有給出初始域類型,則使用。 觸發(fā)實際處理。使用findAndReplaceValue以獲得可空的結(jié)果,而不是一個Optional。 請注意,更換件不得保留其id本身,因為id現(xiàn)有的Document將被商店本身轉(zhuǎn)移到更換件中。還要記住,它findAndReplace只會根據(jù)可能給定的排序順序替換與查詢條件匹配的第一個文檔。 |
|