MongoDB學習筆記(一)

1.MongoDB簡介

 

MongoDB介紹

MongoDB是面向文檔的非關係型數據庫,不是如今使用最廣泛的關係型數據庫,其放棄關係模型的緣由就是爲了得到更加方便的擴展、穩定容錯等特性。面向文檔的基本思路就是:將關係模型中的「行」的概念換成「文檔(document)」模型。面向文檔的模型能夠將文檔和數組內嵌到文檔中。所以,實際中能夠用一條數據表示很是複雜的結構。
MongoDB沒有預約義模式:文檔的鍵(key)和值(value)再也不是固定的類型和大小,並且根據需求要添加或者刪除字段變得更容易了。因爲沒有模式須要更改,一般不須要遷移大量數據。沒必要將全部數據都放到一個模子裏面,應用層能夠處理新增或丟失的鍵。這樣開發者能夠很是容易地變動數據模型。
實際應用中,隨着數據量的增大,數據庫都要進行擴展。擴展有縱向擴展和橫向擴展。縱向擴展是使用計算能力更強的機器,也是最省力的方法,可是很容易達到物理極限,不管花多少錢也買不到最新的機器了。橫向擴展就是經過分區將數據分散到更多的機器上。MongoDB的設計採用橫向擴展。面向文檔的數據模型使它很容易地在多臺服務器之間進行數據分割。還能夠自動處理跨集羣的數據和負載,自動從新分配文檔,以及將用戶請求路由到正確的機器上。開發者根本不用考慮數據庫層次的擴展問題,須要擴展數據庫時,在集羣中添加機器便可,MongoDB會自動處理後續的事情。
MongoDB有如上各類特性,但爲了達到這些,他也放棄了關係型數據庫的某些功能如錶鏈接join和複雜的多行事務。

2017-05-12_214955.png-8kB 
直觀瞭解: 
2017-05-17_165633.png-13kBjava

 

MongoDB的優點與劣勢

 

優點

  1. 快速!基於內存,將熱數據存放在物理內存中(不只僅只是索引和少部分數據),從而提升了總體速度和效率。
  2. 高擴展性!MongoDB的高可用和集羣架構擁有十分高的擴展性。
  3. 自身的FailOver機制!在副本集中,當主庫遇到問題,沒法繼續提供服務的時候,副本集將選舉一個新的主庫繼續提供服務。
  4. JSon格式的數據!MongoDB的Bson和JSon格式的數據十分適合文檔格式的存儲與查詢。
 

劣勢

  1. 應用經驗少!因爲NoSQL興起時間短,應用經驗相比關係型數據庫較少。
  2. 因爲以往用到的都是關係型數據庫,可能會形成使用者一開始的不適應。
  3. 無事務機制!MongoDB自己沒有自帶事務機制,若須要在MongoDB中實現事務機制,需經過一個額外的表,從邏輯上自行實現事務。

 

2.MongoDB與MYSQL對比

數據庫 MongoDB MySQL
數據庫模型 非關係型 關係型
存儲方式 以類JSON的文檔的格式存儲 不一樣引擎有不一樣的存儲方式
查詢語句 MongoDB查詢方式(相似JavaScript的函數) SQL語句
數據處理方式 基於內存,將熱數據存放在物理內存中,從而達到高速讀寫 不一樣引擎有本身的特色
成熟度 新興數據庫,成熟度較低 成熟度高
普遍度 NoSQL數據庫中,比較完善且開源,使用人數在不斷增加 開源數據庫,市場份額不斷增加
事務性 僅支持單文檔事務操做,弱一致性 支持事務操做
佔用空間 佔用空間大 佔用空間小
join操做 MongoDB沒有join MySQL支持join

下面是Mongodb與Mysql的操做命令的對比: 
2017-05-05_102256.png-15kBmysql


 

MongoDB基礎知識與CRUD

1.文檔(document):至關於傳統關係型數據庫的「行」,但比傳統行表示的信息更加複雜。例如:正則表達式

 
{"name":"jack","age":18,"sex":"male"}

2.集合(collection):這個在MongoDB中表明一組文檔,相似於關係型數據庫中的表。但在MongoDB中的表(就是集合)是沒有模式的,你能夠將徹底不一樣的文檔放入同一個集合中.但在實際使用中,爲特定集合隱性規定一種模式。注:當集合裏沒有任何文檔時集合其實也是不存在的。當第一個文檔插入時,集合就會被建立。 
3.數據庫(database):在MongoDB中,一組集合能夠組成一個數據庫。一個MongoDB實例能夠承載多個數據庫。每一個數據庫都有獨立的權限控制。在實際應用中,一般,一個應用的全部數據放置在一個數據庫中。 
4.數據類型:MongoDB中的文檔相似於JSON。JSON是一種簡單的數據交換格式,在數據類型方面,只支持:null,布爾,數字,字符串,數組和對象。這幾種類型在某些實際應用中表現力仍是不夠,好比JSON自己不直接支持日期類型,對於數字,JSON自己也無法區分整數和浮點數,更不能區分32位數字和64位數字。爲此,MongoDB再保留了JSON的各種特性外,又爲其添加了一些數據類型。 
1.null:用於表示空值或不存在的字段。Shell中這樣表示:{"x":null} 
2.布爾:有兩個值,true和false。Shell中這樣使用:{"x":true} 
3.數字:Shell中數字均爲64位浮點數,如在Shell中{"x":3.14}{"x":3}這兩個文檔中的值均是64位的浮點數。 
4.字符串:這個用的最廣,Shell中這樣表示:{"x":"hello world!"} 
5.日期:這個在數據存儲時,存儲的是從標準紀元開始的毫秒數,沒有存儲時區信息。 
6.正則表達式:文檔中能夠包含正則表達式,採用JavaScript的正則表達式語法便可,Shell中這樣表示:{"x":/foobar/i}
7.數組:數組是一組值,既能夠表示爲有序對象(列表,棧,隊列等)也能夠表示無序對象(集合),Shell中這樣表示一個數組:{"things":["pie",3.14]}。 
8.內嵌文檔:把一個文檔整個做爲另外一個文檔某一個鍵對應的值。 
其餘包括二進制數據,代碼等。sql

 

MongoDB入門(Shell基本操做)

運行mongo啓動shell: 
2017-05-05_154321.png-3.8kB 
shell是一個功能完備的JavaScript解釋器,可運行任意的JavaScript程序。這裏不作示例。 
MongoDB的默認數據庫爲"db",該數據庫存儲在data目錄中。 
1.選擇數據庫mongodb

#選擇名test數據庫
use tset

  

2017-05-05_154819.png-1.6kB 
若是忘記了數據庫名稱能夠輸入以下代碼查詢全部數據庫名稱:"show dbs" 命令能夠顯示全部數據的列表shell

 
show dbs

  

2017-05-05_154952.png-2.7kB 
查看數據庫中的集合名:數據庫

 
show collections

  

結果如圖所示: 
2017-05-05_161235.png-2kB 
下表列出了 RDBMS 與 MongoDB 對應的術語: 
2017-05-17_170031.png-4.5kBjson

 

插入文檔

insert函數可將一個文檔插入到集合中去。以一個博客舉例。先建立一個叫post的變量(JavaScript對象)有三個鍵和對應的屬性。插入代碼:數組

 
db.blog.insert(post)

如圖所示: 
2017-05-05_161551.png-6kB 
批量插入bash

 
db.blog.insertMany([{"_id":0},{"_id":1},{"_id":2}])

  

2017-05-05_171812.png-3.5kB

 

查詢文檔

查詢代碼以下:

 
db.blog.find()

如圖所示: 
2017-05-05_161943.png-5kB 
多出來的"_id"就是MongoDB自動建立的默認爲ObjectID類型的對象。在一個集合裏,每一個文檔都由惟一的"_id",確保集合中的每一個文檔都能被惟一標識,它採用12字節的存儲空間,由24個16進制數字組成,可分爲四部分組成:

{0,1,2,3} {4,5,6} {7,8} {9,10,11}
時間戳 機器碼 PID(線程碼) 自增計數器

若是插入文檔時沒有"_id"鍵,系統會爲咱們自動建立一個。 
若只想查看一個文檔,能夠用findOne:

db.blog.findOne()

  

查詢具體的某一個文檔那麼就要以json的形式添加查詢條件,例如:

 
db.blog.find({"title":"My Blog Post"})

  

以上實例中相似於 WHERE 語句:WHERE title = 'My Blog Post';

2017-05-05_162233.png-7.7kB

 

修改文檔

若是給博客新增一個評論功能,則須要新增key-value,用於保存評論數組。

 
post.comments = []

以後用新版本的文檔替換舊版本:

 
db.blog.update({"title":"My Blog Post"},post)

2017-05-05_162757.png-7.3kB

使用修改器:

"$Set":用來指定一個字段的值,若字段不存在,則建立它。
db.users.update({"sex":"male"},{"$Set":{"gift":"happy birthday!"}})
/*這樣只會更新一個文檔,若要更新多個文檔,則須要將update的第四個參數設置爲true*/
db.users.update({"sex":"male"},{"$Set":{"gift":"happy birthday!"}},false,true) 
"$inc":用來增長已有鍵的值,若鍵不存在,就建立它。(與"$Set"相似,專門用來增長數字的,只能用於整形,長整型,雙精度浮點型)
db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}}) 
"$push":會向已有的數組末尾加入一個元素,若數組不存在,則建立數組。與"$each"自操做符一同使用能夠一次添加多個值。
db.stock.ticker.update({"_id":"1"},{"$push":{"hourly":{"$each":[562.667,562.790,562.123]}}}) 
"$addToSet":能夠避免重複插入。若數組內已有相同數據,則不差入。與"$each"自操做符一同使用能夠一次添加多個值。
db.users.update({"_id""1},{"$addToSet":{"emails":"joe@gmail.com"}})
"$push":刪除數組裏的元素.("$pop":將數組當作隊列或棧,從兩端刪除。"$pull":將所匹配到的數組中的值刪除,而不是隻刪除一個)

刪除文檔

db.blog.remove({"title":"My Blog Post"})

2017-05-05_162941.png-2.9kB 
刪除整個集合用drop()

 
db.blog.drop()

索引

MongoDB使用 ensureIndex() 方法來建立索引。

db.COLLECTION_NAME.ensureIndex({KEY:1})

語法中 Key 值爲你要建立的索引字段,1爲指定按升序建立索引,若是你想按降序來建立索引指定爲-1便可。 
固然也能夠給多個字段創建索引

db.col.ensureIndex({"title":1,"description":-1})

管道聚合

MongoDB的聚合管道將MongoDB文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。 
表達式:處理輸入文檔並輸出。表達式是無狀態的,只能用於計算當前聚合管道的文檔,不能處理其它的文檔。 
這裏咱們介紹一下聚合框架中經常使用的幾個操做:

  • $project:修改輸入文檔的結構。能夠用來重命名、增長或刪除域,也能夠用於建立計算結果以及嵌套文檔。
 
db.article.aggregate(
{ $project : {
title : 1 ,
author : 1 ,
}}
);
  • $match:用於過濾數據,只輸出符合條件的文檔。
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
  • $limit:用來限制MongoDB聚合管道返回的文檔數。
db.article.find().limit
  • $skip:在聚合管道中跳過指定數量的文檔,並返回餘下的文檔。
db.article.aggregate( { $skip : 5 });
  • $group:將集合中的文檔分組,可用於統計結果。

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


 

Java操做MongoDB

 

鏈接數據庫

鏈接數據庫,你須要指定數據庫名稱,若是指定的數據庫不存在,mongo會自動建立數據庫。 
所需jar包: mongo-java-driver-3.2.2.jar 
鏈接數據庫的Java代碼以下:

 1 import com.mongodb.MongoClient;
 2 import com.mongodb.client.MongoDatabase;
 3 public class MongoDBJDBC{
 4 public static void main( String args[] ){
 5 try{
 6 // 鏈接到 mongodb 服務
 7 MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
 8 // 鏈接到數據庫
 9 MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
10 System.out.println("Connect to database successfully");
11 }catch(Exception e){
12 System.err.println( e.getClass().getName() + ": " + e.getMessage() );
13 }
14 }
15 }

 

建立集合: 
咱們可使用 com.mongodb.client.MongoDatabase 類中的createCollection()來建立集合 
代碼片斷以下:

 
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
public class MongoDBJDBC{
public static void main( String args[] ){
try{
// 鏈接到 mongodb 服務
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// 鏈接到數據庫
MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
System.out.println("Connect to database successfully");
mongoDatabase.createCollection("test");
System.out.println("集合建立成功");
}catch(Exception e){
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}
}
}

 

 

插入文檔

 
//插入文檔
/**
* 1. 建立文檔 org.bson.Document 參數爲key-value的格式
* 2. 建立文檔集合List<Document>
* 3. 將文檔集合插入數據庫集合中 mongoCollection.insertMany(List<Document>) 插入單個文檔能夠用 mongoCollection.insertOne(Document)
* */
Document document = new Document("title", "MongoDB").
append("description", "database").
append("likes", 100).
append("by", "Fly");
List<Document> documents = new ArrayList<Document>();
documents.add(document);
collection.insertMany(documents);
System.out.println("文檔插入成功");

 

 

查詢文檔

 
//檢索全部文檔
/**
* 1. 獲取迭代器FindIterable<Document>
* 2. 獲取遊標MongoCursor<Document>
* 3. 經過遊標遍歷檢索出的文檔集合
* */
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}

 

 

修改文檔

 
//更新文檔 將文檔中likes=100的文檔修改成likes=200
collection.updateMany(Filters.eq("likes", 100), new Document("$set",new Document("likes",200)));
//檢索查看結果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}

 

 

刪除文檔

 
//刪除符合條件的第一個文檔
collection.deleteOne(Filters.eq("likes", 200));
//刪除全部符合條件的文檔
collection.deleteMany (Filters.eq("likes", 200));
//檢索查看結果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}
相關文章
相關標籤/搜索