恕我直言,牛逼哄哄的MongoDB你可能只會30%

MongoDB閃亮登場

自我介紹

MongoDB 是一個基於分佈式文件存儲的數據庫。由 C++ 語言編寫。旨在爲 WEB 應用提供可擴展的高性能數據存儲解決方案。java

MongoDB 是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。git

MongoDB最大的特色就是無Schema限制,靈活度很高。數據格式是BSON,BSON是一種相似JSON的二進制形式的存儲格式,簡稱Binary JSON 它和JSON同樣,支持內嵌的文檔對象和數組對象。github

跟關係型數據庫概念對比

Mysql MongoDB
Database(數據庫) Database(數據庫)
Table(表) Collection(集合)
Row(行) Document(文檔)
Column(列) Field(字段)

數據格式

MongoDB 將數據存儲爲一個文檔,BSON格式。由key 和 value組成。spring

"_id" : ObjectId("5e141148473cce6a9ef349c7"),
    "title" : "批量更新", 
    "url" : "http://cxytiandi.com/blog/detail/8", 
    "author" : "yinjihuan", 
    "tags" : [
        "java", 
        "mongodb", 
        "spring"
    ], 
    "visit_count" : NumberLong(10), 
    "add_time" : ISODate("2019-02-11T07:10:32.936+0000")
}
複製代碼

使用場景

  • 大數據量存儲場景

MongoDB自帶副本集和分片,天生就適用於大數量場景,無需開發人員經過中間件去分庫分表,很是方便。sql

  • 操做日誌存儲

不少時候,咱們須要存儲一些操做日誌,可能只須要存儲好比最近一個月的,通常的作法是按期去清理,在MongoDB中有固定集合的概念,咱們在建立集合的時候能夠指定大小,當數據量超過大小的時候會自動移除掉老數據。mongodb

  • 爬蟲數據存儲

爬下來的數據有網頁,也有Json格式的數據,通常都會按照表的格式去存儲,若是咱們用了MongoDB就能夠將抓下來的Json數據直接存入集合中,無格式限制。數據庫

  • 社交數據存儲

在社交場景中使用 MongoDB 存儲存儲用戶地址位置信息,經過地理位置索引實現附近的人,附近的地點等。後端

  • 電商商品存儲

不一樣的商品有不一樣的屬性,常見的作法是抽出公共的屬性表,而後和SPU進行關聯,若是用MongoDB的話那麼SPU中直接就能夠內嵌屬性。數組

自我陶醉

MongoDB的功能點不少,可是大部分場景下咱們只用了最簡單的CRUD操做。下面隆重的介紹下MongoDB的功能點,就像你去相親同樣,很差好介紹本身的優勢又怎能讓你對面的菇涼心動呢?安全

CRUD

CRUD也就是增刪改查,這是數據庫最基本的功能,查詢還支持全文檢索,GEO地理位置查詢等。

  • db.collection.insertOne()

單個文檔插入到集合中

  • db.collection.insertMany()

多個文檔插入到集合中

  • db.collection.insert()

單個或者多個文件插入到集合中

  • db.collection.find( )

查詢數據

  • db.inventory.updateOne()

更新單條

  • db.inventory.updateMany()

更新多條

  • db.inventory.deleteOne( )

刪除單條文檔

  • db.inventory.deleteMany()

刪除多條文檔

Aggregation

聚合操做用於數據統計方面,好比Mysql中會有count,sum,group by等功能,在MongoDB中相對應的就是Aggregation聚合操做。

聚合下面有兩種方式來實現咱們須要對數據進行統計的需求,一個是aggregate,一個是MapReduce。

下圖展現了aggregate的執行原理:

圖片

聚合內置了不少函數,使用好了這些函數咱們就能夠統計出咱們想要的數據。

$project:修改輸入文檔的結構。能夠用來重命名、增長或刪除域,也能夠用於建立計算結果以及嵌套文檔。

match:用於過濾數據,只輸出符合條件的文檔。match使用MongoDB的標準查詢操做。

$limit:用來限制MongoDB聚合管道返回的文檔數。

$skip:在聚合管道中跳過指定數量的文檔,並返回餘下的文檔。

$group:將集合中的文檔分組,可用於統計結果。

$sort:將輸入文檔排序後輸出。

$geoNear:輸出接近某一地理位置的有序文檔。

$unwind:將文檔中的某一個數組類型字段拆分紅多條,每條包含數組中的一個值。

下圖展現了MapReduce的執行原理:

圖片

總共4條數據,query指定了查詢條件,只處理status=A的數據。

map階段對數據進行分組聚合,也就是造成了第三部分的效果,根據cust_id去重統計。

reduce中的key也就是cust_id, values也就是彙總的amount集合。而後進行sum操做,最終的結果經過out輸出到一個集合中。

Transactions

MongoDB最開始是不支持事務的,在MongoDB中,對單個文檔的操做是原子性操做。因此再設計的時候可使用嵌入的文檔和數組來描述數據之間的關係,這樣就不用跨多個文檔和集合進行操做,也就經過了單文檔原子性消除了許多實際用例對多文檔事務的須要。

任何事物都是有限制的,某些場景仍是不能徹底經過內嵌的方式來描述數據的關係,仍是會存在多個集合,對於使用MongoDB的用戶來講,若是能支持事務就很方便了。

不負衆望,MongoDB 4.0 版本的發佈,爲咱們帶來了原生的事務操做。

Indexes

索引不用我多說了,做用你們都知道。單索引,組合索引,全文索引,Hash索引等。

db.collection.createIndex({user_id: 1, add_time: 1}, {background: true})
複製代碼

建立索引特別要注意的是將background設置爲true,在建索引的過程會阻塞其它數據庫操做,background可指定之後臺方式建立索引,默認爲false。這但是血的教訓呀,切記切記。

Security

MongoDB中的安全須要重視,目前啓動不知道有沒有強制的限制,之前啓動的時候能夠不指定認證的方式,也就是不須要密碼便可訪問,而後不少人都直接用的默認端口,暴露在公網上,給不法分子有隙可乘,出現了數據被刪,須要用比特幣來找回數據的案例比比皆是。

仍是要開啓安全認證,內置了不少角色,不一樣的角色可操做的內容不同,控制的比較細。

Replication

副本集是一組相同數據集的MongoDB實例,同時在多個節點存儲數據,提升了可用性。主節點負責寫入,從節點負責讀取,提升總體性能。

副本集由下面的組件構成:

Primary:主節點接收全部的寫操做。

Secondaries:從節點會從主節點進行數據的複製,維護跟主節點相同的數據。用於查詢操做。

Arbiter:仲裁節點自己不存儲數據,只參與選舉。

圖片

Sharding

分片是MongoDB絕對的亮點,將數據水平拆分到多個節點。MongoDB的分片是全自動的,咱們只須要配置好分片的規則,它就能自動維護數據並存儲到不一樣節點。MongoDB使用分片來支持大數據量的存儲和高吞吐量的操做。

下圖是Mongodb的分片集羣架構圖:

圖片

MongoDB分片集羣由如下組件夠成:

Shard:每一個shard的數據都是獨立完整的一份。而且能夠做爲副本集部署。

mongos:mongos是查詢路由器,在客戶端和服務端中間的一層,請求會直接到mongos,由mongos路由到具體的Shard。

Config Servers:存儲集羣全部節點、分片數據路由信息。

GridFS

GridFS是MongoDB的一個子模塊,主要用於在MongoDB中存儲文件,至關於MongoDB內置的一個分佈式文件系統。

本質上仍是講文件的數據分塊存儲在集合中,默認的文件集合分爲fs.files和fs.chunks。

fs.files是存儲文件的基本信息,好比文件名,大小,上傳時間,md5等。fs.chunks是存儲文件真正數據的地方,一個文件會被分割成多個chunk塊進行存儲,通常爲256k/個。

圖片

若是你的項目中用到了MongoDB,那麼你可使用GridFS來構建一個文件系統,這樣就不用去購買第三方的存儲服務了。

GridFS的好處是你不用單獨去搭建一個文件系統,直接使用Mongodb自帶的便可,備份,分片都依賴MongoDB,維護起來也方便。

知識點總結

下圖是我本身總結的一些知識點,做爲一個後端開發來講,能掌握下面的內容就已經不錯了,畢竟咱們又不是要去搶DBA的飯碗,若是你們業餘時間要學習的話能夠按照下面的點進行學習,幾年前我錄製了一套視頻,在個人網站上,大部份內容都覆蓋到了。

圖片

工做必用

MongoDB跟Mysql的語法對比

圖片

圖片

Spring Boot中集成MongoDB

加入MongoDB的依賴:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
複製代碼

配置MongoDB的信息:

spring.data.mongodb.database=test
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
// 用戶名,密碼省略.......
複製代碼

直接注入MongoTemplate就能夠操做MongoDB:

@Autowired
private MongoTemplate mongoTemplate;
複製代碼

使用示列

建立一個實體類,對應MongoDB的集合

@Data
@Document(collection = "article_info")
public class Article {
	@Id
	@GeneratedValue
	private Long id;
	@Field("title")
	private String title;
	@Field("url")
	private String url;
	@Field("author")
	private String author;
	@Field("tags")
	private List<String> tags;
	@Field("visit_count")
	private Long visitCount;
	@Field("add_time")
	private Date addTime;
}
複製代碼

最終存儲到數據中的格式以下:

"_id" : ObjectId("5e141148473cce6a9ef349c7"),
    "title" : "批量更新", 
    "url" : "http://cxytiandi.com/blog/detail/8", 
    "author" : "yinjihuan", 
    "tags" : [
        "java", 
        "mongodb", 
        "spring"
    ], 
    "visit_count" : NumberLong(10), 
    "add_time" : ISODate("2019-02-11T07:10:32.936+0000")
}
複製代碼

插入數據

Article article = new Article();
article.setTitle("MongoTemplate 的基本使用 ");
article.setAuthor("yinjihuan");
article.setUrl("http://cxytiandi.com/blog/detail/1");
article.setTags(Arrays.asList("java", "mongodb", "spring"));
article.setVisitCount(0L);
article.setAddTime(new Date());
mongoTemplate.save(article);
複製代碼

數據庫語法

db.article_info.save({
	"title": "批量更新",
	"url": "http://cxytiandi.com/blog/detail/8",
	"author": "yinjihuan",
	"tags": [
		"java",
		"mongodb",
		"spring"
	],
	"visit_count": NumberLong(10),
	"add_time": ISODate("2019-02-11T07:10:32.936+0000")
})
複製代碼

更新數據

Query query = Query.query(Criteria.where("author").is("yinjihuan")); 
Update update = Update.update("title", "MongoTemplate")
				.set("visitCount", 10); 
mongoTemplate.updateMulti(query, update, Article.class);
複製代碼

數據庫語法

db.article_info.updateMany(
	{"author":"yinjihuan"}, 
	{"$set":
	   {
	     "title":"MongoTemplate", 
	     "visit_count": NumberLong(10)
	   }
	}
)
複製代碼

刪除數據

Query query = Query.query(Criteria.where("author").is("yinjihuan")); 
mongoTemplate.remove(query, Article.class);
複製代碼

數據庫語法

db.article_info.remove({"author":"yinjihuan"})
複製代碼

查詢數據

Query query = Query.query(Criteria.where("author").is("yinjihuan")); 
List<Article> articles = mongoTemplate.find(query, Article.class);
複製代碼

數據庫語法

db.article_info.find({"author":"yinjihuan"})
複製代碼

存儲文件

File file = new File("/Users/yinjihuan/Downloads/logo.png");
InputStream content = new FileInputStream(file);
// 存儲文件的額外信息,好比用戶ID,後面要查詢某個用戶的全部文件時就能夠直接查詢
DBObject metadata = new BasicDBObject("userId", "1001");
ObjectId fileId = gridFsTemplate.store(content, file.getName(), "image/png", metadata);
複製代碼

源碼參考

github.com/yinjihuan/s…

客戶端推薦

下載地址:

studio3t.com/download/

圖片

spring-boot-starter-mongodb-pool

最後推薦一個我本身寫的小框架:Spring Boot中加強Mongodb的配置,多數據源,鏈接池

github.com/yinjihuan/s…

感興趣的能夠關注下個人微信公衆號 猿天地,更多技術文章第一時間閱讀。個人GitHub也有一些開源的代碼 github.com/yinjihuan

相關文章
相關標籤/搜索