'十次方社交系統 第3章-文檔型數據庫MongoDB'
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3MongoDB特點
MongoDB 最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建 立索引。它是一個面向集合的,模式自由的文檔型數據庫。
具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支持動態查詢
(4)支持完全索引,包含內部對象
(5)支持複製和故障恢復
(6)使用高效的二進制數據存儲,包括大型對象(如視頻等)
(7)自動處理碎片,以支持雲計算層次的擴展性
(8)支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程序,
社區中也提供了對 Erlang 及.NET 等平臺的驅動程序
(9)文件存儲格式為 BSON(一種 JSON 的擴展)
1.4MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由:文檔(document)、集合(collection)、數據庫(database)這三部分組成的。邏輯結構是面向用戶的,用戶使用 MongoDB 開發應用程序使用的就是邏輯結構。
(1)MongoDB 的文檔(document),相當於關係數據庫中的一行記錄。
(2)多個文檔組成一個集合(collection),相當於關係數據庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是數據庫(database)。
(4)一個 MongoDB 實例支持多個數據庫(database)。
文檔(document)、集合(collection)、數據庫(database)的層次結構如下圖:
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3MongoDB特點
MongoDB 最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建 立索引。它是一個面向集合的,模式自由的文檔型數據庫。
具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支持動態查詢
(4)支持完全索引,包含內部對象
(5)支持複製和故障恢復
(6)使用高效的二進制數據存儲,包括大型對象(如視頻等)
(7)自動處理碎片,以支持雲計算層次的擴展性
(8)支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程序,
社區中也提供了對 Erlang 及.NET 等平臺的驅動程序
(9)文件存儲格式為 BSON(一種 JSON 的擴展)
1.4MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由:文檔(document)、集合(collection)、數據庫(database)這三部分組成的。邏輯結構是面向用戶的,用戶使用 MongoDB 開發應用程序使用的就是邏輯結構。
(1)MongoDB 的文檔(document),相當於關係數據庫中的一行記錄。
(2)多個文檔組成一個集合(collection),相當於關係數據庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是數據庫(database)。
(4)一個 MongoDB 實例支持多個數據庫(database)。
文檔(document)、集合(collection)、數據庫(database)的層次結構如下圖:
下表是MongoDB與MySQL數據庫邏輯結構概念的對比
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3MongoDB特點
MongoDB 最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建 立索引。它是一個面向集合的,模式自由的文檔型數據庫。
具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支持動態查詢
(4)支持完全索引,包含內部對象
(5)支持複製和故障恢復
(6)使用高效的二進制數據存儲,包括大型對象(如視頻等)
(7)自動處理碎片,以支持雲計算層次的擴展性
(8)支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程序,
社區中也提供了對 Erlang 及.NET 等平臺的驅動程序
(9)文件存儲格式為 BSON(一種 JSON 的擴展)
1.4MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由:文檔(document)、集合(collection)、數據庫(database)這三部分組成的。邏輯結構是面向用戶的,用戶使用 MongoDB 開發應用程序使用的就是邏輯結構。
(1)MongoDB 的文檔(document),相當於關係數據庫中的一行記錄。
(2)多個文檔組成一個集合(collection),相當於關係數據庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是數據庫(database)。
(4)一個 MongoDB 實例支持多個數據庫(database)。
文檔(document)、集合(collection)、數據庫(database)的層次結構如下圖:
下表是MongoDB與MySQL數據庫邏輯結構概念的對比
1.5數據類型
基本數據類型
null:用於表示空值或者不存在的字段,{“x”:null}
布爾型:布爾類型有兩個值true和false,{“x”:true}
數值:shell默認使用64為浮點型數值。{“x”:3.14}或{“x”:3}。對於整型值,可以使用NumberInt(4字節符號整數)或NumberLong(8字節符號整數),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
字符串:UTF-8字符串都可以表示為字符串類型的數據,{“x”:“呵呵”}
日期:日期被存儲為自新紀元依賴經過的毫秒數,不存儲時區,{“x”:new Date()}
正則表達式:查詢時,使用正則表達式作為限定條件,語法與JavaScript的正則表達式相同,{“x”[abc]/}
數組:數據列表或數據集可以表示為數組,{“x”: [“a“,“b”,”c”]}
內嵌文檔:文檔可以嵌套其他文檔,被嵌套的文檔作為值來處理,{“x”:{“y”:3 }}
對象Id:對象id是一個12字節的字符串,是文檔的唯一標識,{“x”: objectId() }
二進制數據:二進制數據是一個任意字節的字符串。它不能直接在shell中使用。如果要將非utf-字符保存到數據庫中,二進制數據是唯一的方式。
代碼:查詢和文檔中可以包括任何JavaScript代碼,{“x”:function(){/…/}}
2走進MongoDB
2.1MongoDB安裝與啟動
2.1.1window系統MongoDB安裝
安裝
雙擊“資源\\微服務相關\\配套軟件\\mongodb”中的“mongodb-win32-x86_64-2008plus- ssl-3.2.10-signed.msi” 按照提示步驟安裝即可。安裝完成後,軟件會安裝在C:\\Program Files\\MongoDB 目錄中。
我們要啟動的服務程序就是C:\\Program Files\\MongoDB\\Server\\3.2\\bin目錄下的mongod.exe, 為 了 方 便 我 們 每 次 啟 動 , 我 將 C:\\Program Files\\MongoDB\\Server\\3.2\\bin 設置到環境變量path中。
啟動
(1)首先打開命令提示符,創建一個用於存放數據的目錄
md d:\\data
(2)啟動服務
mongod ‐‐dbpath=d:\\data
我們在啟動信息中可以看到,mongoDB的默認端口是27017 如果我們想改變默認的啟動端口,可以通過–port來指定端口在命令提示符輸入以下命令即可完成登陸
mongo
退出mongodb
exit
1.5.2 Docker 環境下MongoDB安裝
在宿主機創建mongo容器
docker run ‐di ‐‐name=tensquare_mongo ‐p 27017:27017 mongo
遠程登陸
mongo 192.168.184.134
以吐槽表為例講解MongoDB常用命令
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3MongoDB特點
MongoDB 最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建 立索引。它是一個面向集合的,模式自由的文檔型數據庫。
具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支持動態查詢
(4)支持完全索引,包含內部對象
(5)支持複製和故障恢復
(6)使用高效的二進制數據存儲,包括大型對象(如視頻等)
(7)自動處理碎片,以支持雲計算層次的擴展性
(8)支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程序,
社區中也提供了對 Erlang 及.NET 等平臺的驅動程序
(9)文件存儲格式為 BSON(一種 JSON 的擴展)
1.4MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由:文檔(document)、集合(collection)、數據庫(database)這三部分組成的。邏輯結構是面向用戶的,用戶使用 MongoDB 開發應用程序使用的就是邏輯結構。
(1)MongoDB 的文檔(document),相當於關係數據庫中的一行記錄。
(2)多個文檔組成一個集合(collection),相當於關係數據庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是數據庫(database)。
(4)一個 MongoDB 實例支持多個數據庫(database)。
文檔(document)、集合(collection)、數據庫(database)的層次結構如下圖:
下表是MongoDB與MySQL數據庫邏輯結構概念的對比
1.5數據類型
基本數據類型
null:用於表示空值或者不存在的字段,{“x”:null}
布爾型:布爾類型有兩個值true和false,{“x”:true}
數值:shell默認使用64為浮點型數值。{“x”:3.14}或{“x”:3}。對於整型值,可以使用NumberInt(4字節符號整數)或NumberLong(8字節符號整數),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
字符串:UTF-8字符串都可以表示為字符串類型的數據,{“x”:“呵呵”}
日期:日期被存儲為自新紀元依賴經過的毫秒數,不存儲時區,{“x”:new Date()}
正則表達式:查詢時,使用正則表達式作為限定條件,語法與JavaScript的正則表達式相同,{“x”[abc]/}
數組:數據列表或數據集可以表示為數組,{“x”: [“a“,“b”,”c”]}
內嵌文檔:文檔可以嵌套其他文檔,被嵌套的文檔作為值來處理,{“x”:{“y”:3 }}
對象Id:對象id是一個12字節的字符串,是文檔的唯一標識,{“x”: objectId() }
二進制數據:二進制數據是一個任意字節的字符串。它不能直接在shell中使用。如果要將非utf-字符保存到數據庫中,二進制數據是唯一的方式。
代碼:查詢和文檔中可以包括任何JavaScript代碼,{“x”:function(){/…/}}
2走進MongoDB
2.1MongoDB安裝與啟動
2.1.1window系統MongoDB安裝
安裝
雙擊“資源\\微服務相關\\配套軟件\\mongodb”中的“mongodb-win32-x86_64-2008plus- ssl-3.2.10-signed.msi” 按照提示步驟安裝即可。安裝完成後,軟件會安裝在C:\\Program Files\\MongoDB 目錄中。
我們要啟動的服務程序就是C:\\Program Files\\MongoDB\\Server\\3.2\\bin目錄下的mongod.exe, 為 了 方 便 我 們 每 次 啟 動 , 我 將 C:\\Program Files\\MongoDB\\Server\\3.2\\bin 設置到環境變量path中。
啟動
(1)首先打開命令提示符,創建一個用於存放數據的目錄
md d:\\data
(2)啟動服務
mongod ‐‐dbpath=d:\\data
我們在啟動信息中可以看到,mongoDB的默認端口是27017 如果我們想改變默認的啟動端口,可以通過–port來指定端口在命令提示符輸入以下命令即可完成登陸
mongo
退出mongodb
exit
1.5.2 Docker 環境下MongoDB安裝
在宿主機創建mongo容器
docker run ‐di ‐‐name=tensquare_mongo ‐p 27017:27017 mongo
遠程登陸
mongo 192.168.184.134
以吐槽表為例講解MongoDB常用命令
2.2常用命令
2.2.1選擇和創建數據庫
選擇和創建數據庫的語法格式:
use 數據庫名稱
如果數據庫不存在則自動創建
以下語句創建spit數據庫
use spitdb
2.2.2插入與查詢文檔
插入文檔的語法格式:
db.集合名稱.insert(數據);
我們這裡可以插入以下測試數據:
db.spit.insert({content:"聽說十次方課程很給力呀",userid:"1011",nickname:"小雅",visits:NumberInt(902)})
查詢集合的語法格式:
db.集合名稱.find()
如果我們要查詢spit集合的所有文檔,我們輸入以下命令
db.spit.find()
這裡你會發現每條文檔會有一個叫_id的字段,這個相當於我們原來關係數據庫中表的主 鍵,當你在插入文檔記錄時沒有指定該字段,MongoDB會自動創建,其類型是ObjectID 類型。如果我們在插入文檔記錄時指定該字段也可以,其類型可以是ObjectID類型,也可以是MongoDB支持的任意類型。
輸入以下測試語句:
db.spit.insert({_id:"1",content:"我還是沒有想明白到底為啥出 錯",userid:"1012",nickname:"小明",visits:NumberInt(2020)});
db.spit.insert({_id:"2",content:"加班到半夜",userid:"1013",nickname:"凱撒",visits:NumberInt(1023)});
db.spit.insert({_id:"3",content:"手機流量超了咋
辦 ?",userid:"1013",nickname:" 凱 撒 ",visits:NumberInt(111)}); db.spit.insert({_id:"4",content:"堅持就是勝利",userid:"1014",nickname:"諾諾",visits:NumberInt(1223)});
如果我想按一定條件來查詢,比如我想查詢userid為1013的記錄,怎麼辦?很簡單!只要在find()中添加參數即可,參數也是json格式,如下:
db.spit.find({userid:'1013'})
如果你只需要返回符合條件的第一條數據,我們可以使用findOne命令來實現
db.spit.findOne({userid:'1013'})
如果你想返回指定條數的記錄,可以在find方法後調用limit來返回結果,例如:
db.spit.find().limit(3)
2.2.3修改與刪除文檔
修改文檔的語法結構:
db.集合名稱.update(條件,修改後的數據)
db.集合名稱.update(條件,修改後的數據)
db.spit.update({_id:"1"},{visits:NumberInt(1000)})
執行後,我們會發現,這條文檔除了visits字段其它字段都不見了,為了解決這個問題, 我們需要使用修改器$set來實現,命令如下:
db.spit.update({_id:"2"},{$set:{visits:NumberInt(2000)}})
這樣就OK啦。
刪除文檔的語法結構:
db.集合名稱.remove(條件)
以下語句可以將數據全部刪除,請慎用
db.spit.remove({})
如果刪除visits=1000的記錄,輸入以下語句
db.spit.remove({visits:1000})
2.2.4統計條數
統計記錄條件使用count()方法。以下語句統計spit集合的記錄數
db.spit.count()
如果按條件統計 ,例如:統計userid為1013的記錄條數
db.spit.count({userid:"1013"})
2.2.5模糊查詢
MongoDB的模糊查詢是通過正則表達式的方式實現的。格式為:
/模糊查詢字符串/
例如,我要查詢吐槽內容包含“流量”的所有文檔,代碼如下:
db.spit.find({content:/流量/})
如果要查詢吐槽內容中以“加班”開頭的,代碼如下:
db.spit.find({content:/^加班/})
2.2.6大於 小於 不等於
<, <=, >, >= 這個操作符也是很常用的,格式如下:
db.集合名稱.find({ "field" : { $gt: value }}) // 大於: field > value
db.集合名稱.find({ "field" : { $lt: value }}) // 小於: field < value
db.集合名稱.find({ "field" : { $gte: value }}) // 大於等於: field >= value
db.集合名稱.find({ "field" : { $lte: value }}) // 小於等於: field <= value
db.集合名稱.find({ "field" : { $ne: value }}) // 不等於: field != value
示例:查詢吐槽瀏覽量大於1000的記錄
db.spit.find({visits:{$gt:1000}})
2.2.7包含與不包含
包含使用$in操作符。
示例:查詢吐槽集合中userid字段包含1013和1014的文檔
db.spit.find({userid:{$in:["1013","1014"]}})
不包含使用$nin操作符。
示例:查詢吐槽集合中userid字段不包含1013和1014的文檔
db.spit.find({userid:{$nin:["1013","1014"]}})
2.2.8條件連接
我們如果需要查詢同時滿足兩個以上條件,需要使用$and操作符將條件進行關聯。(相當於SQL的and)
格式為:
$and:[ {\t},{\t},{ } ]
示例:查詢吐槽集合中visits大於等於1000 並且小於2000的文檔
db.spit.find({$and:[ {visits:{$gte:1000}} ,{visits:{$lt:2000} }]})
如果兩個以上條件之間是或者的關係,我們使用操作符進行關聯,與前面and的使用方式相同
格式為:
$or:[ {\t},{\t},{\t} ]
示例:查詢吐槽集合中userid為1013,或者瀏覽量小於2000的文檔記錄
db.spit.find({$or:[ {userid:"1013"} ,{visits:{$lt:2000} }]})
2.2.9列值增長
如果我們想實現對某列值在原有值的基礎上進行增加或減少,可以使用$inc運算符來實現
db.spit.update({_id:"2"},{$inc:{visits:NumberInt(1)}}\t)
3Java操作MongoDB
3.1mongodb-driver
mongodb-driver是mongo官方推出的java連接mongoDB的驅動包,相當於JDBC驅動。我們通過一個入門的案例來了解mongodb-driver的基本使用
3.1.1查詢全部記錄
(1)創建工程 mongoDemo, 引入依賴
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb‐driver</artifactId>
<version>3.6.3</version>
</dependency>
</dependencies>
(2)創建測試類
/**
* MongoDb入門小demo
*/
public class MongoDemo {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫MongoCollection<Document> spit = spitdb.getCollection("spit");//
獲取集合合
FindIterable<Document> documents = spit.find();//查詢記錄獲取文檔集
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid")); System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
3.1.2條件查詢
BasicDBObject對象:表示一個具體的記錄,BasicDBObject實現了DBObject,是key- value的數據結構,用起來和HashMap是基本一致的。
(1)查詢userid為1013的記錄
public class MongoDemo1 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合條件
BasicDBObject bson=new BasicDBObject("userid","1013");// 構建查詢FindIterable<Document> documents = spit.find(bson);//查詢記錄獲取結果集合
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid"));
System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
(2)查詢瀏覽量大於1000的記錄
public class MongoDemo2 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫
MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合
BasicDBObject bson=new BasicDBObject("visits",new BasicDBObject("$gt",1000) );// 構建查詢條件
FindIterable<Document> documents = spit.find(bson);//查詢記錄獲取結果集合
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid"));
System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
3.1.3插入數據
public class MongoDemo3 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫
MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合
Map<String,Object> map=new HashMap(); map.put("content","我要吐槽");
map.put("userid","9999");
map.put("visits",123); map.put("publishtime",new Date());
Document document=new Document(map);
spit.insertOne(document);//插入數據client.close();
}
}
3.2SpringDataMongoDB
SpringData家族成員之一,用於操作MongoDb的持久層框架,封裝了底層的mongodb- driver。
官網主頁: https://projects.spring.io/spring-data-mongodb/
我們十次方項目的吐槽微服務就採用SpringDataMongoDB框架
4吐槽微服務
4.1需求分析
採用SpringDataMongoDB框架實現吐槽微服務的持久層。實現功能:
(1)基本增刪改查API
(2)根據上級ID查詢吐槽列表
(3)吐槽點贊
(4)發佈吐槽
4.2代碼編寫
4.2.1模塊搭建
(1)搭建子模塊 tensquare_spit
(2)pom.xml引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_common</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
(3)創建application.yml
server: port: 9006
spring: application:
name: tensquare‐spit #指定服務名
data:
mongodb:
host: 192.168.184.134
database: spitdb
(4)創建啟動類
@SpringBootApplication
public class SpitApplication {
public static void main(String[] args) {
SpringApplication.run(SpitApplication.class, args);
}
@Bean
public IdWorker idWorkker(){ return new IdWorker(1, 1);
}
}
4.2.2基本增刪改查API實現
(1)創建實體類
創建包com.tensquare.spit,包下建包pojo 用於存放實體類,創建實體類
/**
*吐槽
*@author Administrator
*
*/
public class Spit implements Serializable{
@Id
private String _id;
private String content;
private Date publishtime;
private String userid;
private String nickname;
private Integer visits;
private Integer thumbup;
private Integer share;
private Integer comment;
private String state;
private String parentid;
// getter and setter .....
}
(2)創建數據訪問接口
com.tensquare.spit包下創建dao包,包下創建接口
/**
*吐槽數據訪問層
*@author Administrator
*
*/
public interface SpitDao extends MongoRepository<Spit, String>{
}
(3)創建業務邏輯類
com.tensquare.spit包下創建service包,包下創建類
@Service
public class SpitService {
@Autowired
private SpitDao spitDao;
@Autowired
private IdWorker idWorker;
/**
*查詢全部記錄
*@return
*/
public List<Spit> findAll(){ return spitDao.findAll();
}
/**
*根據主鍵查詢實體
*@param id
*@return
*/
public Spit findById(String id){
Spit spit = spitDao.findById(id).get(); return spit;
}
/**
*增加
*@param spit
*/
public void add(Spit spit) { spit.set_id(idWorker.nextId()+""); //主鍵值spitDao.save(spit);
}
/**
*修改
*@param spit
*/
public void update(Spit spit) {
spitDao.save(spit);
}
/**
*刪除
*@param id
*/
public void deleteById(String id) { spitDao.deleteById(id);
}
}
(4)com.tensquare.spit包下創建controller類
@RestController @CrossOrigin @RequestMapping("/spit")
public class SpitController {
@Autowired
private SpitService spitService;
/**
*查詢全部數據
*@return
*/
@RequestMapping(method= RequestMethod.GET)
public Result findAll(){
return new Result(true, StatusCode.OK,"查詢成
功",spitService.findAll());
}
/**
*根據ID查詢
*@param id ID
*@return
*/ @RequestMapping(value="/{id}",method=RequestMethod.GET)
public Result findOne(@PathVariable String id){
return new Result(true,StatusCode.OK,"查詢成
功",spitService.findById(id));
}
/**
*增加
*@param spit
*/ @RequestMapping(method=RequestMethod.POST)
public Result add(@RequestBody Spit spit\t){
spitService.add(spit);
return new Result(true,StatusCode.OK,"增加成功");
}
/**
*修改
*@param spit
*/ @RequestMapping(value="/{id}",method=RequestMethod.PUT)
public Result update(@RequestBody Spit spit,@PathVariable String id )
{
spit.set_id(id); spitService.update(spit);
return new Result(true,StatusCode.OK,"修改成功");
}
/**
*刪除
*@param id
*/ @RequestMapping(value="/{id}",method=RequestMethod.DELETE)
public Result deleteById(@PathVariable String id ){
spitService.deleteById(id);
return new Result(true,StatusCode.OK,"刪除成功");
}
}
4.2.3根據上級ID查詢吐槽列表
(1)SpitDao新增方法定義
/**
*根據上級ID查詢吐槽列表(分頁)
*@param parentid
*@param pageable
*@return
*/
public Page<Spit> findByParentid(String parentid,Pageable pageable);
(2)SpitService新增方法
/**
*根據上級ID查詢吐槽列表
*@param parentid
*@param page
*@param size
*@return
*/
public Page<Spit> findByParentid(String parentid,int page, int size){
PageRequest pageRequest = PageRequest.of(page‐1, size);
return spitDao.findByParentid(parentid, pageRequest);
}
(3)SpitController新增方法
/**
*根據上級ID查詢吐槽分頁數據
*@param page
*@param size
*@return
*/
@RequestMapping(value="/comment/{parentId}/{page}/{size}",method=RequestM
ethod.GET)
public Result findByParentid(@PathVariable String parentId, @PathVariable int page,@PathVariable int size){
Page<Spit> pageList = spitService.findByParentid(parentId,page,
size);
return new Result(true,StatusCode.OK," 查 詢 成 功 ",
new PageResult<Spit>(pageList.getTotalElements(), pageList.getContent() ) );
}
4.2.4吐槽點贊
我們看一下以下點讚的代碼: SpitService 新增updateThumbup方法
public void updateThumbup(String id){
Spit spit = spitDao.findById(id).get();
spit.setThumbup(spit.getThumbup()+1);
spitDao.save(spit);
}
以上方法雖然實現起來比較簡單,但是執行效率並不高,因為我只需要將點贊數加1就可以了,沒必要查詢出所有字段修改後再更新所有字段。
我們可以使用MongoTemplate類來實現對某列的操作。
(1)修改SpitService
@Autowired
private MongoTemplate mongoTemplate;
/**
*點贊
*@param id
*/
public void updateThumbup(String id){ Query query=new Query();
query.addCriteria(Criteria.where("_id").is(id));
Update update=new Update();
update.inc("thumbup",1);
mongoTemplate.updateFirst(query,update,"spit");
}
(2)SpitController新增方法
* @return
*/ @RequestMapping(value="/thumbup/{id}",method=RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id){
spitService.updateThumbup(id);
return new Result(true,StatusCode.OK,"點贊成功");
}
4.2.5控制不能重複點贊
我們可以通過redis控制用戶不能重複點贊
(1)首先引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐redis</artifactId>
</dependency>
(2)修改application.yml
redis:
host: 192.168.184.135
(3)修改SpitController代碼邏輯
@Autowired
private RedisTemplate redisTemplate;
/**
*吐槽點贊
*@param id
*@return
*/
@RequestMapping(value = "/thumbup/{id}", method = RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id){
//判斷用戶是否點過贊
String userid="2023";// 後邊我們會修改為當前登陸的用戶
if(redisTemplate.opsForValue().get("thumbup_"+userid+"_"+ id)!=null){
return new Result(false,StatusCode.REPERROR,"你已經點過讚了");
}
spitService.updateThumbup(id);
redisTemplate.opsForValue().set( "thumbup_"+userid+"_"+ id,"1");
return new Result(true,StatusCode.OK,"點贊成功");
}
4.2.6發佈吐槽
修改SpitService的add方法
/**
*發佈吐槽(或吐槽評論)
*@param spit
*/
public void add(Spit spit){
spit.set_id( idWorker.nextId()+"" );
spit.setPublishtime(new Date());//發佈日期
spit.setVisits(0);//瀏覽量spit.setShare(0);//分享數
spit.setThumbup(0);//點贊數
spit.setComment(0);//回覆數spit.setState("1");//狀態
if(spit.getParentid()!=null && !"".equals(spit.getParentid())){//
如果存在上級ID,評論
Query query=new Query();
query.addCriteria(Criteria.where("_id").is(spit.getParentid()));
Update update=new Update(); update.inc("comment",1);
mongoTemplate.updateFirst(query,update,"spit");
}
spitDao.save(spit);
}
5文章評論功能開發
5.1表結構分析
集合結構:
學習目標:
理解MongoDb的特點和體系結構
掌握常用的MongoDB命令
能夠運用Java操作MongoDB
使用SpringDataMongoDB完成吐槽微服務的開發
1MongoDB簡介
1.1吐槽和評論數據特點分析
吐槽和評論兩項功能存在以下特點:
(1)數據量大
(2)寫入操作頻繁
(3)價值較低
對於這樣的數據,我們更適合使用MongoDB來實現數據的存儲
1.2什麼是MongoDB
MongoDB 是一個跨平臺的,面向文檔的數據庫,是當前 NoSQL 數據庫產品中最熱門的一種。它介於關係數據庫和非關係數據庫之間,是非關係數據庫當中功能最豐富,最 像關係數據庫的產品。它支持的數據結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以存儲比較複雜的數據類型。
MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3MongoDB特點
MongoDB 最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建 立索引。它是一個面向集合的,模式自由的文檔型數據庫。
具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支持動態查詢
(4)支持完全索引,包含內部對象
(5)支持複製和故障恢復
(6)使用高效的二進制數據存儲,包括大型對象(如視頻等)
(7)自動處理碎片,以支持雲計算層次的擴展性
(8)支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程序,
社區中也提供了對 Erlang 及.NET 等平臺的驅動程序
(9)文件存儲格式為 BSON(一種 JSON 的擴展)
1.4MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由:文檔(document)、集合(collection)、數據庫(database)這三部分組成的。邏輯結構是面向用戶的,用戶使用 MongoDB 開發應用程序使用的就是邏輯結構。
(1)MongoDB 的文檔(document),相當於關係數據庫中的一行記錄。
(2)多個文檔組成一個集合(collection),相當於關係數據庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是數據庫(database)。
(4)一個 MongoDB 實例支持多個數據庫(database)。
文檔(document)、集合(collection)、數據庫(database)的層次結構如下圖:
下表是MongoDB與MySQL數據庫邏輯結構概念的對比
1.5數據類型
基本數據類型
null:用於表示空值或者不存在的字段,{“x”:null}
布爾型:布爾類型有兩個值true和false,{“x”:true}
數值:shell默認使用64為浮點型數值。{“x”:3.14}或{“x”:3}。對於整型值,可以使用NumberInt(4字節符號整數)或NumberLong(8字節符號整數),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
字符串:UTF-8字符串都可以表示為字符串類型的數據,{“x”:“呵呵”}
日期:日期被存儲為自新紀元依賴經過的毫秒數,不存儲時區,{“x”:new Date()}
正則表達式:查詢時,使用正則表達式作為限定條件,語法與JavaScript的正則表達式相同,{“x”[abc]/}
數組:數據列表或數據集可以表示為數組,{“x”: [“a“,“b”,”c”]}
內嵌文檔:文檔可以嵌套其他文檔,被嵌套的文檔作為值來處理,{“x”:{“y”:3 }}
對象Id:對象id是一個12字節的字符串,是文檔的唯一標識,{“x”: objectId() }
二進制數據:二進制數據是一個任意字節的字符串。它不能直接在shell中使用。如果要將非utf-字符保存到數據庫中,二進制數據是唯一的方式。
代碼:查詢和文檔中可以包括任何JavaScript代碼,{“x”:function(){/…/}}
2走進MongoDB
2.1MongoDB安裝與啟動
2.1.1window系統MongoDB安裝
安裝
雙擊“資源\\微服務相關\\配套軟件\\mongodb”中的“mongodb-win32-x86_64-2008plus- ssl-3.2.10-signed.msi” 按照提示步驟安裝即可。安裝完成後,軟件會安裝在C:\\Program Files\\MongoDB 目錄中。
我們要啟動的服務程序就是C:\\Program Files\\MongoDB\\Server\\3.2\\bin目錄下的mongod.exe, 為 了 方 便 我 們 每 次 啟 動 , 我 將 C:\\Program Files\\MongoDB\\Server\\3.2\\bin 設置到環境變量path中。
啟動
(1)首先打開命令提示符,創建一個用於存放數據的目錄
md d:\\data
(2)啟動服務
mongod ‐‐dbpath=d:\\data
我們在啟動信息中可以看到,mongoDB的默認端口是27017 如果我們想改變默認的啟動端口,可以通過–port來指定端口在命令提示符輸入以下命令即可完成登陸
mongo
退出mongodb
exit
1.5.2 Docker 環境下MongoDB安裝
在宿主機創建mongo容器
docker run ‐di ‐‐name=tensquare_mongo ‐p 27017:27017 mongo
遠程登陸
mongo 192.168.184.134
以吐槽表為例講解MongoDB常用命令
2.2常用命令
2.2.1選擇和創建數據庫
選擇和創建數據庫的語法格式:
use 數據庫名稱
如果數據庫不存在則自動創建
以下語句創建spit數據庫
use spitdb
2.2.2插入與查詢文檔
插入文檔的語法格式:
db.集合名稱.insert(數據);
我們這裡可以插入以下測試數據:
db.spit.insert({content:"聽說十次方課程很給力呀",userid:"1011",nickname:"小雅",visits:NumberInt(902)})
查詢集合的語法格式:
db.集合名稱.find()
如果我們要查詢spit集合的所有文檔,我們輸入以下命令
db.spit.find()
這裡你會發現每條文檔會有一個叫_id的字段,這個相當於我們原來關係數據庫中表的主 鍵,當你在插入文檔記錄時沒有指定該字段,MongoDB會自動創建,其類型是ObjectID 類型。如果我們在插入文檔記錄時指定該字段也可以,其類型可以是ObjectID類型,也可以是MongoDB支持的任意類型。
輸入以下測試語句:
db.spit.insert({_id:"1",content:"我還是沒有想明白到底為啥出 錯",userid:"1012",nickname:"小明",visits:NumberInt(2020)});
db.spit.insert({_id:"2",content:"加班到半夜",userid:"1013",nickname:"凱撒",visits:NumberInt(1023)});
db.spit.insert({_id:"3",content:"手機流量超了咋
辦 ?",userid:"1013",nickname:" 凱 撒 ",visits:NumberInt(111)}); db.spit.insert({_id:"4",content:"堅持就是勝利",userid:"1014",nickname:"諾諾",visits:NumberInt(1223)});
如果我想按一定條件來查詢,比如我想查詢userid為1013的記錄,怎麼辦?很簡單!只要在find()中添加參數即可,參數也是json格式,如下:
db.spit.find({userid:'1013'})
如果你只需要返回符合條件的第一條數據,我們可以使用findOne命令來實現
db.spit.findOne({userid:'1013'})
如果你想返回指定條數的記錄,可以在find方法後調用limit來返回結果,例如:
db.spit.find().limit(3)
2.2.3修改與刪除文檔
修改文檔的語法結構:
db.集合名稱.update(條件,修改後的數據)
db.集合名稱.update(條件,修改後的數據)
db.spit.update({_id:"1"},{visits:NumberInt(1000)})
執行後,我們會發現,這條文檔除了visits字段其它字段都不見了,為了解決這個問題, 我們需要使用修改器$set來實現,命令如下:
db.spit.update({_id:"2"},{$set:{visits:NumberInt(2000)}})
這樣就OK啦。
刪除文檔的語法結構:
db.集合名稱.remove(條件)
以下語句可以將數據全部刪除,請慎用
db.spit.remove({})
如果刪除visits=1000的記錄,輸入以下語句
db.spit.remove({visits:1000})
2.2.4統計條數
統計記錄條件使用count()方法。以下語句統計spit集合的記錄數
db.spit.count()
如果按條件統計 ,例如:統計userid為1013的記錄條數
db.spit.count({userid:"1013"})
2.2.5模糊查詢
MongoDB的模糊查詢是通過正則表達式的方式實現的。格式為:
/模糊查詢字符串/
例如,我要查詢吐槽內容包含“流量”的所有文檔,代碼如下:
db.spit.find({content:/流量/})
如果要查詢吐槽內容中以“加班”開頭的,代碼如下:
db.spit.find({content:/^加班/})
2.2.6大於 小於 不等於
<, <=, >, >= 這個操作符也是很常用的,格式如下:
db.集合名稱.find({ "field" : { $gt: value }}) // 大於: field > value
db.集合名稱.find({ "field" : { $lt: value }}) // 小於: field < value
db.集合名稱.find({ "field" : { $gte: value }}) // 大於等於: field >= value
db.集合名稱.find({ "field" : { $lte: value }}) // 小於等於: field <= value
db.集合名稱.find({ "field" : { $ne: value }}) // 不等於: field != value
示例:查詢吐槽瀏覽量大於1000的記錄
db.spit.find({visits:{$gt:1000}})
2.2.7包含與不包含
包含使用$in操作符。
示例:查詢吐槽集合中userid字段包含1013和1014的文檔
db.spit.find({userid:{$in:["1013","1014"]}})
不包含使用$nin操作符。
示例:查詢吐槽集合中userid字段不包含1013和1014的文檔
db.spit.find({userid:{$nin:["1013","1014"]}})
2.2.8條件連接
我們如果需要查詢同時滿足兩個以上條件,需要使用$and操作符將條件進行關聯。(相當於SQL的and)
格式為:
$and:[ {\t},{\t},{ } ]
示例:查詢吐槽集合中visits大於等於1000 並且小於2000的文檔
db.spit.find({$and:[ {visits:{$gte:1000}} ,{visits:{$lt:2000} }]})
如果兩個以上條件之間是或者的關係,我們使用操作符進行關聯,與前面and的使用方式相同
格式為:
$or:[ {\t},{\t},{\t} ]
示例:查詢吐槽集合中userid為1013,或者瀏覽量小於2000的文檔記錄
db.spit.find({$or:[ {userid:"1013"} ,{visits:{$lt:2000} }]})
2.2.9列值增長
如果我們想實現對某列值在原有值的基礎上進行增加或減少,可以使用$inc運算符來實現
db.spit.update({_id:"2"},{$inc:{visits:NumberInt(1)}}\t)
3Java操作MongoDB
3.1mongodb-driver
mongodb-driver是mongo官方推出的java連接mongoDB的驅動包,相當於JDBC驅動。我們通過一個入門的案例來了解mongodb-driver的基本使用
3.1.1查詢全部記錄
(1)創建工程 mongoDemo, 引入依賴
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb‐driver</artifactId>
<version>3.6.3</version>
</dependency>
</dependencies>
(2)創建測試類
/**
* MongoDb入門小demo
*/
public class MongoDemo {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫MongoCollection<Document> spit = spitdb.getCollection("spit");//
獲取集合合
FindIterable<Document> documents = spit.find();//查詢記錄獲取文檔集
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid")); System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
3.1.2條件查詢
BasicDBObject對象:表示一個具體的記錄,BasicDBObject實現了DBObject,是key- value的數據結構,用起來和HashMap是基本一致的。
(1)查詢userid為1013的記錄
public class MongoDemo1 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合條件
BasicDBObject bson=new BasicDBObject("userid","1013");// 構建查詢FindIterable<Document> documents = spit.find(bson);//查詢記錄獲取結果集合
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid"));
System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
(2)查詢瀏覽量大於1000的記錄
public class MongoDemo2 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫
MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合
BasicDBObject bson=new BasicDBObject("visits",new BasicDBObject("$gt",1000) );// 構建查詢條件
FindIterable<Document> documents = spit.find(bson);//查詢記錄獲取結果集合
for(Document document:documents){ //
System.out.println("內容:"+\tdocument.getString("content"));
System.out.println("用戶ID:"+document.getString("userid"));
System.out.println("瀏覽量:"+document.getInteger("visits"));
}
client.close();//關閉連接
}
}
3.1.3插入數據
public class MongoDemo3 {
public static void main(String[] args) {
MongoClient client=new MongoClient("192.168.184.134");//創建連接
MongoDatabase spitdb = client.getDatabase("spitdb");//打開數據庫
MongoCollection<Document> spit = spitdb.getCollection("spit");//獲取集合
Map<String,Object> map=new HashMap(); map.put("content","我要吐槽");
map.put("userid","9999");
map.put("visits",123); map.put("publishtime",new Date());
Document document=new Document(map);
spit.insertOne(document);//插入數據client.close();
}
}
3.2SpringDataMongoDB
SpringData家族成員之一,用於操作MongoDb的持久層框架,封裝了底層的mongodb- driver。
官網主頁: https://projects.spring.io/spring-data-mongodb/
我們十次方項目的吐槽微服務就採用SpringDataMongoDB框架
4吐槽微服務
4.1需求分析
採用SpringDataMongoDB框架實現吐槽微服務的持久層。實現功能:
(1)基本增刪改查API
(2)根據上級ID查詢吐槽列表
(3)吐槽點贊
(4)發佈吐槽
4.2代碼編寫
4.2.1模塊搭建
(1)搭建子模塊 tensquare_spit
(2)pom.xml引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_common</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
(3)創建application.yml
server: port: 9006
spring: application:
name: tensquare‐spit #指定服務名
data:
mongodb:
host: 192.168.184.134
database: spitdb
(4)創建啟動類
@SpringBootApplication
public class SpitApplication {
public static void main(String[] args) {
SpringApplication.run(SpitApplication.class, args);
}
@Bean
public IdWorker idWorkker(){ return new IdWorker(1, 1);
}
}
4.2.2基本增刪改查API實現
(1)創建實體類
創建包com.tensquare.spit,包下建包pojo 用於存放實體類,創建實體類
/**
*吐槽
*@author Administrator
*
*/
public class Spit implements Serializable{
@Id
private String _id;
private String content;
private Date publishtime;
private String userid;
private String nickname;
private Integer visits;
private Integer thumbup;
private Integer share;
private Integer comment;
private String state;
private String parentid;
// getter and setter .....
}
(2)創建數據訪問接口
com.tensquare.spit包下創建dao包,包下創建接口
/**
*吐槽數據訪問層
*@author Administrator
*
*/
public interface SpitDao extends MongoRepository<Spit, String>{
}
(3)創建業務邏輯類
com.tensquare.spit包下創建service包,包下創建類
@Service
public class SpitService {
@Autowired
private SpitDao spitDao;
@Autowired
private IdWorker idWorker;
/**
*查詢全部記錄
*@return
*/
public List<Spit> findAll(){ return spitDao.findAll();
}
/**
*根據主鍵查詢實體
*@param id
*@return
*/
public Spit findById(String id){
Spit spit = spitDao.findById(id).get(); return spit;
}
/**
*增加
*@param spit
*/
public void add(Spit spit) { spit.set_id(idWorker.nextId()+""); //主鍵值spitDao.save(spit);
}
/**
*修改
*@param spit
*/
public void update(Spit spit) {
spitDao.save(spit);
}
/**
*刪除
*@param id
*/
public void deleteById(String id) { spitDao.deleteById(id);
}
}
(4)com.tensquare.spit包下創建controller類
@RestController @CrossOrigin @RequestMapping("/spit")
public class SpitController {
@Autowired
private SpitService spitService;
/**
*查詢全部數據
*@return
*/
@RequestMapping(method= RequestMethod.GET)
public Result findAll(){
return new Result(true, StatusCode.OK,"查詢成
功",spitService.findAll());
}
/**
*根據ID查詢
*@param id ID
*@return
*/ @RequestMapping(value="/{id}",method=RequestMethod.GET)
public Result findOne(@PathVariable String id){
return new Result(true,StatusCode.OK,"查詢成
功",spitService.findById(id));
}
/**
*增加
*@param spit
*/ @RequestMapping(method=RequestMethod.POST)
public Result add(@RequestBody Spit spit\t){
spitService.add(spit);
return new Result(true,StatusCode.OK,"增加成功");
}
/**
*修改
*@param spit
*/ @RequestMapping(value="/{id}",method=RequestMethod.PUT)
public Result update(@RequestBody Spit spit,@PathVariable String id )
{
spit.set_id(id); spitService.update(spit);
return new Result(true,StatusCode.OK,"修改成功");
}
/**
*刪除
*@param id
*/ @RequestMapping(value="/{id}",method=RequestMethod.DELETE)
public Result deleteById(@PathVariable String id ){
spitService.deleteById(id);
return new Result(true,StatusCode.OK,"刪除成功");
}
}
4.2.3根據上級ID查詢吐槽列表
(1)SpitDao新增方法定義
/**
*根據上級ID查詢吐槽列表(分頁)
*@param parentid
*@param pageable
*@return
*/
public Page<Spit> findByParentid(String parentid,Pageable pageable);
(2)SpitService新增方法
/**
*根據上級ID查詢吐槽列表
*@param parentid
*@param page
*@param size
*@return
*/
public Page<Spit> findByParentid(String parentid,int page, int size){
PageRequest pageRequest = PageRequest.of(page‐1, size);
return spitDao.findByParentid(parentid, pageRequest);
}
(3)SpitController新增方法
/**
*根據上級ID查詢吐槽分頁數據
*@param page
*@param size
*@return
*/
@RequestMapping(value="/comment/{parentId}/{page}/{size}",method=RequestM
ethod.GET)
public Result findByParentid(@PathVariable String parentId, @PathVariable int page,@PathVariable int size){
Page<Spit> pageList = spitService.findByParentid(parentId,page,
size);
return new Result(true,StatusCode.OK," 查 詢 成 功 ",
new PageResult<Spit>(pageList.getTotalElements(), pageList.getContent() ) );
}
4.2.4吐槽點贊
我們看一下以下點讚的代碼: SpitService 新增updateThumbup方法
public void updateThumbup(String id){
Spit spit = spitDao.findById(id).get();
spit.setThumbup(spit.getThumbup()+1);
spitDao.save(spit);
}
以上方法雖然實現起來比較簡單,但是執行效率並不高,因為我只需要將點贊數加1就可以了,沒必要查詢出所有字段修改後再更新所有字段。
我們可以使用MongoTemplate類來實現對某列的操作。
(1)修改SpitService
@Autowired
private MongoTemplate mongoTemplate;
/**
*點贊
*@param id
*/
public void updateThumbup(String id){ Query query=new Query();
query.addCriteria(Criteria.where("_id").is(id));
Update update=new Update();
update.inc("thumbup",1);
mongoTemplate.updateFirst(query,update,"spit");
}
(2)SpitController新增方法
* @return
*/ @RequestMapping(value="/thumbup/{id}",method=RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id){
spitService.updateThumbup(id);
return new Result(true,StatusCode.OK,"點贊成功");
}
4.2.5控制不能重複點贊
我們可以通過redis控制用戶不能重複點贊
(1)首先引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐redis</artifactId>
</dependency>
(2)修改application.yml
redis:
host: 192.168.184.135
(3)修改SpitController代碼邏輯
@Autowired
private RedisTemplate redisTemplate;
/**
*吐槽點贊
*@param id
*@return
*/
@RequestMapping(value = "/thumbup/{id}", method = RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id){
//判斷用戶是否點過贊
String userid="2023";// 後邊我們會修改為當前登陸的用戶
if(redisTemplate.opsForValue().get("thumbup_"+userid+"_"+ id)!=null){
return new Result(false,StatusCode.REPERROR,"你已經點過讚了");
}
spitService.updateThumbup(id);
redisTemplate.opsForValue().set( "thumbup_"+userid+"_"+ id,"1");
return new Result(true,StatusCode.OK,"點贊成功");
}
4.2.6發佈吐槽
修改SpitService的add方法
/**
*發佈吐槽(或吐槽評論)
*@param spit
*/
public void add(Spit spit){
spit.set_id( idWorker.nextId()+"" );
spit.setPublishtime(new Date());//發佈日期
spit.setVisits(0);//瀏覽量spit.setShare(0);//分享數
spit.setThumbup(0);//點贊數
spit.setComment(0);//回覆數spit.setState("1");//狀態
if(spit.getParentid()!=null && !"".equals(spit.getParentid())){//
如果存在上級ID,評論
Query query=new Query();
query.addCriteria(Criteria.where("_id").is(spit.getParentid()));
Update update=new Update(); update.inc("comment",1);
mongoTemplate.updateFirst(query,update,"spit");
}
spitDao.save(spit);
}
5文章評論功能開發
5.1表結構分析
集合結構:
4.2.1新增評論
(1)修改tensquare_article工程的pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐mongodb</artifactId>
</dependency>
(2)修改application.yml ,在spring節點下新增配置
data:
mongodb:
host: 192.168.184.134
database: recruitdb
(3)創建實體類
/**
*文章評論(mongoDB)
*@author Administrator
*
*/
public class Comment implements Serializable{
@Id
private String _id;
private String articleid;
private String content;
private String userid;
private String parentid;
private Date publishdate;
//getter and setter....
}
(4)創建數據訪問接口
/**
*評論Dao
*@author Administrator
*
*/
public interface CommentDao extends MongoRepository<Comment, String> {
}
(5)創建業務邏輯類
@Service
public class CommentService {
@Autowired
private CommentDao commentDao;
@Autowired
private IdWorker idWorker;
public void add(Comment comment){
comment.setId( idWorker.nextId()+""\t); commentDao.save(comment);
}
}
(6)創建控制器類
@RestController
@CrossOrigin @RequestMapping("/comment")
public class CommentController {
@Autowired
private CommentService commentService;
@RequestMapping(method= RequestMethod.POST)
public Result save(@RequestBody Comment comment){ commentService.add(comment);
return new Result(true, StatusCode.OK, "提交成功 ");
}
}
4.2.2根據文章ID查詢評論列表
(1)CommentDao新增方法定義
/**
*根據文章ID查詢評論列表
*@param articleid
*@return
*/
public List<Comment> findByArticleid(String articleid);
(2)CommentService新增方法
public List<Comment> findByArticleid(String articleid){
return commentDao.findByArticleid(articleid);
}
(3)CommentController新增方法
@RequestMapping(value="/article/{articleid}",method= RequestMethod.GET)
public Result findByArticleid(@PathVariable String articleid){
return new Result(true, StatusCode.OK, "查詢成功",
commentService.findByArticleid(articleid));
}
面試問題總結
你在項目中有沒有使用到mongodb?
你的工程是如何操作MongoDB的?
spring data mongodb
在項目的哪些場景下使用MongoDB ?
吐槽 、文章評論
為什麼在吐槽和文章評論中使用Mongodb而不使用mysql?
吐槽和評論都是數據量較大且價值較低的數據,為了減輕mysql的壓力,我們使用mongodb