文章目錄
- 1. MongoDB相關概念
- 1.1 業務應用場景
- 1.2 MongoDB簡介
- 1.3 體系結構
- 1.4 數據模型
- 1.5 MongoDB的特點
- 2. docker安裝mongodb
- 3. springboot集成
- 3.1 文件結構
- 3.2 增刪改查
- 3.2.1 增加insert
- 3.2.2 保存save
- 3.2.3 更新update
- 3.2.4 查詢
- 3.2.5 刪除
1. MongoDB相關概念
1.1 業務應用場景
傳統的關系型數據庫(如MySQL),在數據操作的“三高”需求以及應對Web2.0的網站需求面前,顯得力不從心。
解釋:“三高”需求:
? High performance - 對數據庫高并發讀寫的需求。
? Huge Storage - 對海量數據的高效率存儲和訪問的需求。
? High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求。
而MongoDB可應對“三高”需求。
具體的應用場景如:
1)社交場景,使用 MongoDB 存儲存儲用戶信息,以及用戶發表的朋友圈信息,通過地理位置索引實現附近的人、地點等功能。
2)游戲場景,使用 MongoDB 存儲游戲用戶信息,用戶的裝備、積分等直接以內嵌文檔的形式存儲,方便查詢、高效率存儲和訪問。
3)物流場景,使用 MongoDB 存儲訂單信息,訂單狀態在運送過程中會不斷更新,以 MongoDB 內嵌數組的形式來存儲,一次查詢就能將訂單所有的變更讀取出來。
4)物聯網場景,使用 MongoDB 存儲所有接入的智能設備信息,以及設備匯報的日志信息,并對這些信息進行多維度的分析。
5)視頻直播,使用 MongoDB 存儲用戶信息、點贊互動信息等。
這些應用場景中,數據操作方面的共同特點是:
(1)數據量大
(2)寫入操作頻繁(讀寫都很頻繁)
(3)價值較低的數據,對事務性要求不高
對于這樣的數據,我們更適合使用MongoDB來實現數據的存儲。
什么時候選擇MongoDB
在架構選型上,除了上述的三個特點外,如果你還猶豫是否要選擇它?可以考慮以下的一些問題:
應用不需要事務及復雜 join 支持
新應用,需求會變,數據模型無法確定,想快速迭代開發
應用需要2000-3000以上的讀寫QPS(更高也可以)
應用需要TB甚至 PB 級別數據存儲
應用發展迅速,需要能快速水平擴展
應用要求存儲的數據不丟失
應用需要99.999%高可用
應用需要大量的地理位置查詢、文本查詢
如果上述有1個符合,可以考慮 MongoDB,2個及以上的符合,選擇 MongoDB 絕不會后悔。
思考:如果用MySQL呢?
答:相對MySQL,可以以更低的成本解決問題(包括學習、開發、運維等成本)
1.2 MongoDB簡介
MongoDB是一個開源、高性能、無模式的文檔型數據庫,當初的設計就是用于簡化開發和方便擴展,是NoSQL數據庫產品中的一種。是最像關系型數據庫(MySQL)的非關系型數據庫。
它支持的數據結構非常松散,是一種類似于 JSON 的 格式叫BSON,所以它既可以存儲比較復雜的數據類型,又相當的靈活。
MongoDB中的記錄是一個文檔,它是一個由字段和值對(field:value)組成的數據結構。MongoDB文檔類似于JSON對象,即一個文檔認為就是一個對象。字段的數據類型是字符型,它的值除了使用基本的一些類型外,還可以包括其他文檔、普通數組和文檔數組。
1.3 體系結構
MySQL和MongoDB對比
SQL術語/概念 | MongoDB術語/概念 | 解釋/說明 |
---|---|---|
database | database | 數據庫 |
table | collection | 數據庫表/集合 |
row | document | 數據記錄行/文檔 |
column | field | 數據字段/域 |
index | index | 索引 |
table joins | 表連接,MongoDB不支持 | |
嵌入文檔 | MongoDB通過嵌入式文檔來替代多表連接 | |
primary key | primary key | 主鍵,MongoDB自動將_id字段設置為主鍵 |
1.4 數據模型
MongoDB的最小存儲單位就是文檔(document)對象。文檔(document)對象對應于關系型數據庫的行。數據在MongoDB中以BSON(Binary-JSON)文檔的格式存儲在磁盤上。
BSON(Binary Serialized Document Format)是一種類json的一種二進制形式的存儲格式,簡稱Binary JSON。BSON和JSON一樣,支持內嵌的文檔對象和數組對象,但是BSON有JSON沒有的一些數據類型,如Date和BinData類型。
BSON采用了類似于 C 語言結構體的名稱、對表示方法,支持內嵌的文檔對象和數組對象,具有輕量性、可遍歷性、高效性的三個特點,可以有效描述非結構化數據和結構化數據。這種格式的優點是靈活性高,但它的缺點是空間利用率不是很理想。
Bson中,除了基本的JSON類型:string,integer,boolean,double,null,array和object,mongo還使用了特殊的數據類型。這些類型包括date,object id,binary data,regular expression 和code。每一個驅動都以特定語言的方式實現了這些類型,查看你的驅動的文檔來獲取詳細信息。
BSON數據類型參考列表:
數據類型 | 描述 | 舉例 |
---|---|---|
字符串 | UTF-8字符串都可表示為字符串類型的數據 | {“x” : “foobar”} |
對象id | 對象id是文檔的12字節的唯一 ID | {“X” :ObjectId() } |
布爾值 | 真或者假:true或者false | {“x”:true}+ |
數組 | 值的集合或者列表可以表示成數組 | {“x” : [“a”, “b”, “c”]} |
32位整數 | 類型不可用。JavaScript僅支持64位浮點數,所以32位整數會被自動轉換。 | shell是不支持該類型的,shell中默認會轉換成64位浮點數 |
64位整數 | 不支持這個類型。shell會使用一個特殊的內嵌文檔來顯示64位整數 | shell是不支持該類型的,shell中默認會轉換成64位浮點數 |
64位浮點數 | shell中的數字就是這一種類型 | {“x”:3.14159,“y”:3} |
null | 表示空值或者未定義的對象 | {“x”:null} |
undefined | 文檔中也可以使用未定義類型 | {“x”:undefined} |
符號 | shell不支持,shell會將數據庫中的符號類型的數據自動轉換成字符串 | |
正則表達式 | 文檔中可以包含正則表達式,采用JavaScript的正則表達式語法 | {“x” : /foobar/i} |
代碼 | 文檔中還可以包含JavaScript代碼 | {“x” : function() { /* …… */ }} |
二進制數據 | 二進制數據可以由任意字節的串組成,不過shell中無法使用 | |
最大值/最小值 | BSON包括一個特殊類型,表示可能的最大值。shell中沒有這個類型。 |
提示:
shell默認使用64位浮點型數值。{“x”:3.14}或{“x”:3}。對于整型值,可以使用NumberInt(4字節符號整數)或NumberLong(8字節符號整數),{“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)}
1.5 MongoDB的特點
MongoDB主要有如下特點:
(1)高性能:
MongoDB提供高性能的數據持久性。特別是,
對嵌入式數據模型的支持減少了數據庫系統上的I/O活動。
索引支持更快的查詢,并且可以包含來自嵌入式文檔和數組的鍵。(文本索引解決搜索的需求、TTL索引解決歷史數據自動過期的需求、地理位置索引可用于構建各種 O2O 應用)
mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持滿足各種場景需求。
Gridfs解決文件存儲的需求。
(2)高可用性:
MongoDB的復制工具稱為副本集(replica set),它可提供自動故障轉移和數據冗余。
(3)高擴展性:
MongoDB提供了水平可擴展性作為其核心功能的一部分。
分片將數據分布在一組集群的機器上。(海量數據存儲,服務能力水平擴展)
從3.4開始,MongoDB支持基于片鍵創建數據區域。在一個平衡的集群中,MongoDB將一個區域所覆蓋的讀寫只定向到該區域內的那些片。
(4)豐富的查詢支持:
MongoDB支持豐富的查詢語言,支持讀和寫操作(CRUD),比如數據聚合、文本搜索和地理空間查詢等。
(5)其他特點:如無模式(動態模式)、靈活的文檔模型
2. docker安裝mongodb
單機安裝
1. 拉取鏡像
docker pull mongo:latest
//2. 創建掛載目錄
//mkdir -p /root/data/mongodata 可以不用,直接用~/data/mongodata
2. 運行容器
docker run -di --name mongo-service \
--restart=always \
-p 27017:27017 \
-v ~/data/mongodata:/data mongo:latest
連接mongodb
studio3t是mongodb優秀的客戶端工具。官方地址在https://studio3t.com/
3. springboot集成
3.1 文件結構
工程結構
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ganz</groupId><artifactId>mongodb-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 繼承Spring boot --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- mongodb --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version></dependency></dependencies>
</project>
application.yml
server:port: 9998
spring:data:mongodb:host: 192.168.200.131port: 27017database: test-db
# username: root
# password: root
# authentication-database: admin
pojo
@Data
@Document("ap_associate_words")
public class ApAssociateWords implements Serializable {private static final long serialVersionUID = 1L;private String id;/*** 聯想詞*/private String associateWords;/*** 創建時間*/private Date createdTime;/*** 得分*/private Integer score;}
測試類
@SpringBootTest(classes = MongoApplication.class)
@RunWith(SpringRunner.class)
public class MongoTest {@Autowiredprivate MongoTemplate mongoTemplate;/*** 單個增加*/@Testpublic void testInsert(){ApAssociateWords apAssociateWords =new ApAssociateWords();apAssociateWords.setId("1");apAssociateWords.setAssociateWords("今天5月22日");apAssociateWords.setCreatedTime(new Date());mongoTemplate.insert(apAssociateWords);}
}
3.2 增刪改查
3.2.1 增加insert
- 單個增加
@Test
public void testInsert(){ApAssociateWords apAssociateWords =new ApAssociateWords();apAssociateWords.setId("1");apAssociateWords.setAssociateWords("今天5月22日");apAssociateWords.setCreatedTime(new Date());mongoTemplate.insert(apAssociateWords);
}
運行結果
- 批量增加
@Test
public void testBatchInsert(){ArrayList<ApAssociateWords> list = new ArrayList<>();for (int i=0;i<10;i++){ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setId((i+10)+"");apAssociateWords.setAssociateWords("今天是這學期第"+i+"天");apAssociateWords.setCreatedTime(new Date());int score =(int)Math.random()*100;apAssociateWords.setScore(score);list.add(apAssociateWords);}mongoTemplate.insertAll(list);
}
運行結果
3.2.2 保存save
不同于insert和update
當id不存在的時候,insert;當id存在的時候,update
/*** 保存:當id不存在的時候,插入* 當id存在的時候,修改*/@Testpublic void testSave(){ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setId("1");apAssociateWords.setAssociateWords("今天5月22日");apAssociateWords.setCreatedTime(new Date());apAssociateWords.setScore(65);mongoTemplate.save(apAssociateWords);}
運行結果
3.2.3 更新update
/*** 修改*/
@Test
public void testUpdate(){//Query 相當于mysql中update的where后的條件Query query = Query.query(Criteria.where("score").gt(60));//update 相當于mysql中update的set后的新數據Update update = new Update();update.set("associateWords","分數大于60");//updateFirst 修改符合條件的第一條//mongoTemplate.updateFirst(query,update,ApAssociateWords.class);//updateMulti 修改所有符合條件的mongoTemplate.updateMulti(query,update,ApAssociateWords.class);
}
3.2.4 查詢
/*** 查詢*/
@Test
public void testFind(){Query query =Query.query(Criteria.where("associateWords")// 模糊查詢.regex("今天")// 10 < score < 30.and("score").gt(10).lt(50));// 排序 相當于order by score ascquery.with(Sort.by(Sort.Direction.ASC,"score"));// 分頁 相當于 limit 0, 2query.with(PageRequest.of(0,2));List<ApAssociateWords> result = mongoTemplate.find(query, ApAssociateWords.class);for (ApAssociateWords apAssociateWords:result){System.out.println(apAssociateWords);}
}
運行結果
3.2.5 刪除
/*** 刪除*/
@Test
public void testRemove(){// _id = "15"Query query = Query.query(Criteria.where("_id").is("15"));mongoTemplate.remove(query, ApAssociateWords.class);
}
運行結果,刪掉了_id為"15"的文檔