tensquare-3 文件型資料庫MongoDB
第3章-文件型資料庫MongoDB
1 MongoDB簡介
1.1 吐槽和評論資料特點分析
吐槽和評論兩項功能存在以下特點:
(1)資料量大
(2)寫入操作頻繁
(3)價值較低 對於這樣的資料,我們更適合使用MongoDB來實現資料的儲存
1.2 什麼是MongoDB
MongoDB 是一個跨平臺的,面向文件的資料庫,是當前 NoSQL 資料庫產品中最熱 門的一種。它介於關聯式資料庫和非關聯式資料庫之間,是非關聯式資料庫當中功能最豐富,最 像關聯式資料庫的產品。它支援的資料結構非常鬆散,是類似 JSON 的 BSON 格式,因此可以 儲存比較複雜的資料型別。 MongoDB 的官方網站地址是:http://www.mongodb.org/
1.3 MongoDB特點
MongoDB 最大的特點是他支援的查詢語言非常強大,其語法有點類似於物件導向 的查詢語言,幾乎可以實現類似關聯式資料庫單表查詢的絕大部分功能,而且還支援對資料建 立索引。它是一個面向集合的,模式自由的文件型資料庫。 具體特點總結如下:
(1)面向集合儲存,易於儲存物件型別的資料
(2)模式自由
(3)支援動態查詢
(4)支援完全索引,包含內部物件
(5)支援複製和故障恢復
(6)使用高效的二進位制資料儲存,包括大型物件(如視訊等)
(7)自動處理碎片,以支援雲端計算層次的擴充套件性
(8)支援 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++語言的驅動程 序,社群中也提供了對 Erlang 及.NET 等平臺的驅動程式
(9) 檔案儲存格式為 BSON(一種 JSON 的擴充套件)
1.4 MongoDB體系結構
MongoDB 的邏輯結構是一種層次結構。主要由: 文件(document)、集合(collection)、資料庫(database)這三部分組成的。邏輯結構是面 向使用者的,使用者使用 MongoDB 開發應用程式使用的就是邏輯結構。
(1)MongoDB 的文件(document),相當於關聯式資料庫中的一行記錄。
(2)多個文件組成一個集合(collection),相當於關聯式資料庫的表。
(3)多個集合(collection),邏輯上組織在一起,就是資料庫(database)。
(4)一個 MongoDB 例項支援多個資料(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
1.5.2 Docker 環境下MongoDB安裝
在宿主機建立mongo容器
docker run -di --name=tensquare_mongo ‐p 27017:27017
MongoDB的圖形化管理工具可以使用NoSQLBooster for MongoDB
以吐槽表為例講解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(條件,修改後的資料)
如果我們想修改_id為1的記錄,瀏覽量為1000,輸入以下語句:
db.spit.update({_id:"1"},{visits:NumberInt(1000)})
執行後,我們會發現,這條文件除了visits欄位其它欄位都不見了
,為了解決這個問題, 我們需要使用修改器$set來實現,命令如下:
db.spit.update({_id:"2"},{$set:{visits:NumberInt(2000)}})
刪除文件的語法結構:
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:[ { },{ },{ } ]
示例:查詢吐槽集合中visits大於等於1000 並且小於2000的文件
db.spit.find({$and:[ {visits:{$gte:1000}} ,{visits:{$lt:2000} }]})
如果兩個以上條件之間是或者的關係,我們使用 操作符進行關聯,與前面and的使用 方式相同
格式為:
$or:[ { },{ },{ } ]
示例:查詢吐槽集合中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)}} )
3 Java操作MongoDB
3.1 SpringDataMongoDB
SpringData家族成員之一,用於操作MongoDb的持久層框架,封裝了底層的mongodb- driver。
我們十次方專案的吐槽微服務就採用SpringDataMongoDB框架
4 吐槽微服務
4.1 需求分析
採用SpringDataMongoDB框架實現吐槽微服務的持久層。 實現功能:
(1)基本增刪改查API
(2)根據上級ID查詢吐槽列表
(3)吐槽點贊
(4)釋出吐槽
4.2 程式碼編寫
4.2.1 模組搭建
(1)搭建子模組 tensquare_spit
(2)pom.xml引入依賴
<dependency>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(3)建立application.yml
server:
port: 9006
spring:
application:
name: tensquare-spit
data:
mongodb:
host: 192.168.11.131
database: spitdb
(4)建立啟動類
@SpringBootApplication
public class SpitApplication {
public static void main(String[] args) {
SpringApplication.run(SpitApplication.class);
}
@Bean
public IdWorker idWorker(){
return new IdWorker(1,1);
}
}
4.2.2基本增刪改查API實現
(1)建立實體類
建立包com.tensquare.spit,包下建包pojo 用於存放實體類,建立實體類
package com.tensquare.search.spit.pojo;
import org.springframework.data.annotation.Id;
import java.io.Serializable;
import java.util.Date;
/**
* 吐槽
*/
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;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPublishtime() {
return publishtime;
}
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getVisits() {
return visits;
}
public void setVisits(Integer visits) {
this.visits = visits;
}
public Integer getThumbup() {
return thumbup;
}
public void setThumbup(Integer thumbup) {
this.thumbup = thumbup;
}
public Integer getShare() {
return share;
}
public void setShare(Integer share) {
this.share = share;
}
public Integer getComment() {
return comment;
}
public void setComment(Integer comment) {
this.comment = comment;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getParentid() {
return parentid;
}
public void setParentid(String parentid) {
this.parentid = parentid;
}
}
(2)建立資料訪問介面
com.tensquare.spit包下建立dao包,包下建立介面
package com.tensquare.search.spit.dao;
import com.tensquare.search.spit.pojo.Spit;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface SpitDao extends MongoRepository<Spit, String> {
Page<Spit> findByParentid(String parentId, Pageable pageable);
}
(3)建立業務邏輯類
com.tensquare.spit包下建立service包,包下建立類
package com.tensquare.search.spit.service;
import com.tensquare.search.spit.dao.SpitDao;
import com.tensquare.search.spit.pojo.Spit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import util.IdWorker;
import java.util.List;
@Service
public class SpitService {
@Autowired
SpitDao spitDao;
@Autowired
IdWorker idWorker;
@Autowired
MongoTemplate mongoTemplate;
public List<Spit> findAll() {
return spitDao.findAll();
}
/*** 增加 * @param spit */
public void add(Spit spit) {
spit.set_id(String.valueOf(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);
}
/**
* 根據id查詢記錄
* @param id
* @return
*/
public Spit findById(String id) {
return spitDao.findById(id).get();
}
/**
* 根據上級ID查詢吐槽列表(分頁)
* @param parentId
* @param page
* @param size
* @return
*/
public Page<Spit> findByParentId(String parentId, int page, int size){
PageRequest request = PageRequest.of(page-1, size);
return spitDao.findByParentid(parentId, request);
}
}
4.2.3 吐槽點贊
我們看一下以下點讚的程式碼: SpitService 新增updateThumbup方法
/**
* 吐槽點贊
* @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");
}
4.2.4 控制不能重複點贊
我們可以通過redis控制使用者不能重複點贊
(1)首先引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
修改application.yml, 在spring的節點下
加;
redis:
host: 192.168.11.131
(3)修改SpitController程式碼邏輯
@Autowired
private RedisTemplate redisTemplate;
/**
* 點贊
*
* @param spitId
* @return
*/
@RequestMapping(value = "/thumbup/{spitId}", method = RequestMethod.PUT)
public Result updateThumbup(@PathVariable String spitId) {
String userid = "2023";// 後邊我們會修改為當前登陸的使用者
if(redisTemplate.opsForValue().get("thumbup_" + userid + "_" + spitId) != null){
return new Result(false,StatusCode.REPERROR,"你已經點過讚了");
}
spitService.updateThumbup(spitId);
return new Result(true, StatusCode.OK, "點贊成功");
}
4.2.5 釋出吐槽
修改SpitService的add方法
/*** 增加 * @param spit */
public void add(Spit spit) {
/*** 釋出吐槽(或吐槽評論) * @param 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);
}
相關文章
- Python操作MongoDB文件資料庫PythonMongoDB資料庫
- SpringBoot整合Mongodb文件資料庫Spring BootMongoDB資料庫
- 聊聊非關係型資料庫MongoDB索引資料庫MongoDB索引
- 分散式文件儲存資料庫之MongoDB索引管理分散式資料庫MongoDB索引
- 分散式文件儲存資料庫之MongoDB副本集分散式資料庫MongoDB
- MongoDB資料庫MongoDB資料庫
- nodejs之MongoDB 非關係型資料庫NodeJSMongoDB資料庫
- 分散式文件儲存資料庫之MongoDB分片叢集分散式資料庫MongoDB
- 分散式文件儲存資料庫之MongoDB訪問控制分散式資料庫MongoDB
- 大資料時代的資料儲存,非關係型資料庫MongoDB大資料資料庫MongoDB
- 分散式文件儲存資料庫之MongoDB基礎入門分散式資料庫MongoDB
- MongoDB 資料庫操作MongoDB資料庫
- mongodb資料庫操作MongoDB資料庫
- nodejs操作mongodb資料庫(mongodb)NodeJSMongoDB資料庫
- mongodb資料庫中插入資料MongoDB資料庫
- 悉數11種主流NoSQL文件型資料庫HQSQL資料庫
- 以MongoDB為例與關係型資料庫比較MongoDB資料庫
- 分散式文件儲存資料庫之MongoDB備份與恢復分散式資料庫MongoDB
- mongodb_資料型別(null/字串/數字/日期/內嵌文件/陣列等)MongoDB資料型別Null字串陣列
- 初試MongoDB資料庫MongoDB資料庫
- mongodb 如何建立資料庫MongoDB資料庫
- 快速掌握 MongoDB 資料庫MongoDB資料庫
- MongoDB資料庫安裝MongoDB資料庫
- 學習MongoDB資料庫MongoDB資料庫
- mongoDB資料庫之聚合MongoDB資料庫
- MongoDB資料庫備份MongoDB資料庫
- MongoDB資料庫入門MongoDB資料庫
- MongoDB資料庫簡介MongoDB資料庫
- Mongodb資料庫連線MongoDB資料庫
- 資料庫——MongoDB——>Java篇資料庫MongoDBJava
- MongoDB資料庫效能分析MongoDB資料庫
- 啟動MongoDB資料庫MongoDB資料庫
- 資料庫_SQL-MongoDB資料庫SQLMongoDB
- 文件型 NoSQL 資料庫 SequoiaDB 正式宣佈開源SQL資料庫
- 分析型資料庫:分散式分析型資料庫資料庫分散式
- Express 文件(資料庫整合)Express資料庫
- mongodb資料庫如何建立索引?MongoDB資料庫索引
- Mongodb記憶體資料庫MongoDB記憶體資料庫