本篇依然是MongoDB curd中的一篇,主要介紹document的更新,主要內容如下
- 常見型別成員的修改
- 陣列型別成員的增刪改
- document型別成員的增刪改
I. 基本使用
首先是準備好基本環境,可以參考博文
在開始之前,先封裝一個輸出方法,用於列印修改後的record物件
private void queryAndPrint(Query query, String tag) {
System.out.println("------------- after " + tag + " age -------------");
Map record = mongoTemplate.findOne(query, Map.class, COLLECTION_NAME);
System.out.println("query records: " + record);
System.out.println("------------- end " + tag + " age --------------\n");
}
複製程式碼
1. 基本型別修改
mongodb支援我們常見的各種基本型別,而MongoTemplate也封裝了不少對應的修改方法,最基礎的修改,主要是藉助Update
來實現
常見的使用姿勢如:
a. 基本使用姿勢
public void basicUpdate() {
/*
* {
* "_id" : ObjectId("5c49b07ce6652f7e1add1ea2"),
* "age" : 100,
* "name" : "一灰灰blog",
* "desc" : "Java Developer",
* "add" : [
* "額外增加"
* ],
* "date" : ISODate("2019-01-28T08:00:08.373Z"),
* "doc" : {
* "key" : "小目標",
* "value" : "升職加薪,迎娶白富美"
* }
* }
*/
// 1. 直接修改值的內容
Query query = new Query(Criteria.where("_id").is("5c49b07ce6652f7e1add1ea2"));
Update update = new Update().set("desc", "Java & Python Developer");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "set");
}
複製程式碼
輸出結果為:
------------- after set age -------------
query records: {_id=5c49b07ce6652f7e1add1ea2, age=100, name=一灰灰blog, desc=Java & Python Developer, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}}
------------- end set age --------------
複製程式碼
b. 數字增加/減少
數字型別修改,使用 org.springframework.data.mongodb.core.query.Update#inc
// 數字修改,實現新增or減少
Update numUp = new Update().inc("age", 20L);
mongoTemplate.updateFirst(query, numUp, COLLECTION_NAME);
queryAndPrint(query, "inc");
複製程式碼
輸出結果為:
------------- after inc age -------------
query records: {_id=5c49b07ce6652f7e1add1ea2, age=120, name=一灰灰blog, desc=Java & Python Developer, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}}
------------- end inc age --------------
複製程式碼
c. 數字比較修改
數字簡單比較之後修改,如org.springframework.data.mongodb.core.query.Update#max
// 數字比較修改
Update cmpUp = new Update().max("age", 88);
mongoTemplate.updateFirst(query, cmpUp, COLLECTION_NAME);
queryAndPrint(query, "cmp");
複製程式碼
輸出結果
------------- after cmp age -------------
query records: {_id=5c49b07ce6652f7e1add1ea2, age=120, name=一灰灰blog, desc=Java & Python Developer, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}}
------------- end cmp age --------------
複製程式碼
d. 乘法
乘法運算, 主要使用 org.springframework.data.mongodb.core.query.Update#multiply
// 乘法
Update mulUp = new Update().multiply("age", 3);
mongoTemplate.updateFirst(query, mulUp, COLLECTION_NAME);
queryAndPrint(query, "multiply");
複製程式碼
輸出結果
------------- after multiply age -------------
query records: {_id=5c49b07ce6652f7e1add1ea2, age=360.0, name=一灰灰blog, desc=Java & Python Developer, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}}
------------- end multiply age --------------
複製程式碼
e. 日期修改
日期修改, 如 org.springframework.data.mongodb.core.query.Update#currentDate
// 日期修改
Update dateUp = new Update().currentDate("date");
mongoTemplate.updateFirst(query, dateUp, COLLECTION_NAME);
queryAndPrint(query, "date");
複製程式碼
輸出結果
------------- after date age -------------
query records: {_id=5c49b07ce6652f7e1add1ea2, age=360.0, name=一灰灰blog, desc=Java & Python Developer, add=[額外增加], date=Mon Feb 18 19:34:56 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}}
------------- end date age --------------
複製程式碼
2. field修改
不同於mysql的列表是固定的,mongodb的field可以增加、刪除和重新命名,下面分別看下三種case如何使用
/**
* 修改欄位名,新增欄位,刪除欄位
*/
public void fieldUpdate() {
/**
* {
* "_id" : ObjectId("5c6a7ada10ffc647d301dd62"),
* "age" : 28.0,
* "name" : "一灰灰blog",
* "desc" : "Java Developer",
* "add" : [
* "額外增加"
* ],
* "date" : ISODate("2019-01-28T08:00:08.373Z"),
* "doc" : {
* "key" : "小目標",
* "value" : "升職加薪,迎娶白富美"
* }
* }
*/
Query query = new Query(Criteria.where("_id").is("5c6a7ada10ffc647d301dd62"));
renameFiled(query);
addField(query);
delField(query);
}
複製程式碼
a. 重新命名
利用org.springframework.data.mongodb.core.query.Update#rename
來實現重新命名,需要注意的是,當修改的docuemnt沒有這個成員時,相當於沒有任務操作
private void renameFiled(Query query) {
Update update = new Update().rename("desc", "skill");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "rename");
// 如果欄位不存在,相當於沒有更新
update = new Update().rename("desc", "s-skill");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "rename Not exists!");
}
複製程式碼
輸出結果如下,後面一個語句相當於沒有執行
------------- after rename age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end rename age --------------
------------- after rename Not exists! age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end rename Not exists! age --------------
複製程式碼
b. 新增成員
新增也是直接利用的Update#set
方法,當存在時,修改;不存在時,新增
- 另外提一下
setOnInsert
, 如果要更新的文件存在那麼$setOnInsert操作符不做任何處理;
private void addField(Query query) {
// 新增一個欄位
// 直接使用set即可
Update update = new Update().set("new-skill", "Python");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "addField");
// 當更新一個不存在的文件時,可以使用setOnInsert
// 如果要更新的文件存在那麼$setOnInsert操作符不做任何處理;
}
複製程式碼
輸出結果如下:
------------- after addField age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer, new-skill=Python}
------------- end addField age --------------
複製程式碼
c. 刪除成員
刪除document中的某個成員,藉助org.springframework.data.mongodb.core.query.Update#unset
, 正好與新增對上
private void delField(Query query) {
// 刪除欄位,如果不存在,則不操作
Update update = new Update().unset("new-skill");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "delField");
}
複製程式碼
輸出結果如下
------------- after delField age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end delField age --------------
複製程式碼
3. 陣列操作
在MongoDB的document中,有兩個有意思的型別,一個是陣列,一個是document(即可以巢狀),這裡則主要介紹下如何運算元組中的成員
/**
* 更新文件中欄位為陣列成員的值
*/
public void updateInnerArray() {
/**
* {
* "_id" : ObjectId("5c6a7ada10ffc647d301dd62"),
* "age" : 28.0,
* "name" : "一灰灰blog",
* "skill" : "Java Developer",
* "add" : [
* "額外增加"
* ],
* "date" : ISODate("2019-01-28T08:00:08.373Z"),
* "doc" : {
* "key" : "小目標",
* "value" : "升職加薪,迎娶白富美"
* }
* }
*/
Query query = new Query(Criteria.where("_id").is("5c6a7ada10ffc647d301dd62"));
this.addData2Array(query);
this.batchAddData2Array(query);
this.delArrayData(query);
this.updateArrayData(query);
}
複製程式碼
a. 新增到陣列中
在陣列中新增一個資料,提供了兩種方式,一個是org.springframework.data.mongodb.core.query.Update#addToSet(java.lang.String, java.lang.Object)
,一個是org.springframework.data.mongodb.core.query.Update#push(java.lang.String, java.lang.Object)
;兩個的區別在於前者不能插入重複資料,後者可以
private void addData2Array(Query query) {
// 新加一個元素到陣列,如果已經存在,則不會加入
String insert = "新新增>>" + System.currentTimeMillis();
Update update = new Update().addToSet("add", insert);
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "add2List");
// push 新增元素,允許出現重複的資料
update = new Update().push("add", 10);
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "push2List");
}
複製程式碼
輸出結果
------------- after add2List age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, 新新增>>1550489696892], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end add2List age --------------
------------- after push2List age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, 新新增>>1550489696892, 10], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end push2List age --------------
複製程式碼
b. 批量新增
一次新增多個,藉助addToSet
的each
來實現
private void batchAddData2Array(Query query) {
// 批量插入資料到陣列中, 注意不會將重複的資料丟入mongo陣列中
Update update = new Update().addToSet("add").each("2", "2", "3");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "batchAdd2List");
}
複製程式碼
輸出結果:
------------- after batchAdd2List age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, 新新增>>1550489696892, 10, 2, 3], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end batchAdd2List age --------------
複製程式碼
c. 刪除
藉助pull來精確刪除某個值
private void delArrayData(Query query) {
// 刪除陣列中元素
Update update = new Update().pull("add", "2");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "delArrayData");
}
複製程式碼
輸出如下,注意對比,2
沒有了
------------- after delArrayData age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, 新新增>>1550489696892, 10, 3], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end delArrayData age --------------
複製程式碼
d. 修改
修改,首先的問題是要定位,確定刪除陣列中某個下標的元素,這裡藉助了一個有意思的站位
- 定位刪除的陣列元素方法:
arrayKey.index
arrayKey
是陣列在docment中的名index
表示要刪除的索引
一個例項如下
private void updateArrayData(Query query) {
// 使用set,field.index 來更新陣列中的值
// 更新陣列中的元素,如果元素存在,則直接更新;如果陣列個數小於待更新的索引位置,則前面補null
Update update = new Update().set("add.1", "updateField");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "updateListData");
update = new Update().set("add.10", "nullBefore");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "updateListData");
}
複製程式碼
輸出結果,注意後面的,如果陣列個數小於待更新的索引位置,則前面補null
------------- after updateListData age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, updateField, 10, 3], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end updateListData age --------------
------------- after updateListData age -------------
query records: {_id=5c6a7ada10ffc647d301dd62, age=28.0, name=一灰灰blog, add=[額外增加, updateField, 10, 3, null, null, null, null, null, null, nullBefore], date=Mon Jan 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end updateListData age --------------
複製程式碼
4. document操作
內嵌文件,可以所是MongoDB的一個特色了,我們則來看下如何進行操作
/**
* 更新文件中欄位為document型別的值
*/
public void updateInnerDoc() {
/**
* {
* "_id" : ObjectId("5c6a956b10ffc647d301dd63"),
* "age" : 18.0,
* "name" : "一灰灰blog",
* "date" : ISODate("2019-02-28T08:00:08.373Z"),
* "doc" : {
* "key" : "小目標",
* "value" : "升職加薪,迎娶白富美"
* },
* "skill" : "Java Developer"
* }
*/
Query query = new Query(Criteria.where("_id").is("5c6a956b10ffc647d301dd63"));
this.addFieldToDoc(query);
this.updateFieldOfDoc(query);
this.delFieldOfDoc(query);
}
複製程式碼
a. 新增
藉助前面的站位思想,就很好實現了,定位元素的方式採用
- docName.fieldName
- docName 為內嵌文件在docunent中的fieldName
- fieldName 為內嵌文件內部需要修改的fieldName
private void addFieldToDoc(Query query) {
// 內嵌doc新增field
Update update = new Update().set("doc.title", "好好學習,天天向上!");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "addFieldToDoc");
}
複製程式碼
輸出如下
------------- after addFieldToDoc age -------------
query records: {_id=5c6a956b10ffc647d301dd63, age=18.0, name=一灰灰blog, date=Thu Feb 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美, title=好好學習,天天向上!}, skill=Java Developer}
------------- end addFieldToDoc age --------------
複製程式碼
c. 修改
private void updateFieldOfDoc(Query query) {
// 內嵌doc修改field
Update update = new Update().set("doc.title", "新的標題:一灰灰Blog!");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "updateFieldOfDoc");
}
複製程式碼
輸出如下
------------- after updateFieldOfDoc age -------------
query records: {_id=5c6a956b10ffc647d301dd63, age=18.0, name=一灰灰blog, date=Thu Feb 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美, title=新的標題:一灰灰Blog!}, skill=Java Developer}
------------- end updateFieldOfDoc age --------------
複製程式碼
d. 刪除
private void delFieldOfDoc(Query query) {
// 刪除內嵌doc中的field
Update update = new Update().unset("doc.title");
mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
queryAndPrint(query, "delFieldOfDoc");
}
複製程式碼
輸出如下
------------- after delFieldOfDoc age -------------
query records: {_id=5c6a956b10ffc647d301dd63, age=18.0, name=一灰灰blog, date=Thu Feb 28 16:00:08 CST 2019, doc={key=小目標, value=升職加薪,迎娶白富美}, skill=Java Developer}
------------- end delFieldOfDoc age --------------
複製程式碼
II. 其他
0. 專案
- 工程:spring-boot-demo
- 子module:111-mongo-template
1. 一灰灰Blog
- 一灰灰Blog個人部落格 blog.hhui.top
- 一灰灰Blog-Spring專題部落格 spring.hhui.top
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 宣告
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog
知識星球