MongoDB是面向文檔的非關係型數據庫,不是如今使用最廣泛的關係型數據庫,其放棄關係模型的緣由就是爲了得到更加方便的擴展、穩定容錯等特性。面向文檔的基本思路就是:將關係模型中的「行」的概念換成「文檔(document)」模型。面向文檔的模型能夠將文檔和數組內嵌到文檔中。所以,實際中能夠用一條數據表示很是複雜的結構。 MongoDB沒有預約義模式:文檔的鍵(key)和值(value)再也不是固定的類型和大小,並且根據需求要添加或者刪除字段變得更容易了。因爲沒有模式須要更改,一般不須要遷移大量數據。沒必要將全部數據都放到一個模子裏面,應用層能夠處理新增或丟失的鍵。這樣開發者能夠很是容易地變動數據模型。 實際應用中,隨着數據量的增大,數據庫都要進行擴展。擴展有縱向擴展和橫向擴展。縱向擴展是使用計算能力更強的機器,也是最省力的方法,可是很容易達到物理極限,不管花多少錢也買不到最新的機器了。橫向擴展就是經過分區將數據分散到更多的機器上。MongoDB的設計採用橫向擴展。面向文檔的數據模型使它很容易地在多臺服務器之間進行數據分割。還能夠自動處理跨集羣的數據和負載,自動從新分配文檔,以及將用戶請求路由到正確的機器上。開發者根本不用考慮數據庫層次的擴展問題,須要擴展數據庫時,在集羣中添加機器便可,MongoDB會自動處理後續的事情。 MongoDB有如上各類特性,但爲了達到這些,他也放棄了關係型數據庫的某些功能如錶鏈接join和複雜的多行事務。
直觀瞭解:
java
數據庫 | MongoDB | MySQL |
---|---|---|
數據庫模型 | 非關係型 | 關係型 |
存儲方式 | 以類JSON的文檔的格式存儲 | 不一樣引擎有不一樣的存儲方式 |
查詢語句 | MongoDB查詢方式(相似JavaScript的函數) | SQL語句 |
數據處理方式 | 基於內存,將熱數據存放在物理內存中,從而達到高速讀寫 | 不一樣引擎有本身的特色 |
成熟度 | 新興數據庫,成熟度較低 | 成熟度高 |
普遍度 | NoSQL數據庫中,比較完善且開源,使用人數在不斷增加 | 開源數據庫,市場份額不斷增加 |
事務性 | 僅支持單文檔事務操做,弱一致性 | 支持事務操做 |
佔用空間 | 佔用空間大 | 佔用空間小 |
join操做 | MongoDB沒有join | MySQL支持join |
下面是Mongodb與Mysql的操做命令的對比:
mysql
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
運行mongo啓動shell:
shell是一個功能完備的JavaScript解釋器,可運行任意的JavaScript程序。這裏不作示例。
MongoDB的默認數據庫爲"db",該數據庫存儲在data目錄中。
1.選擇數據庫mongodb
#選擇名test數據庫 use tset
若是忘記了數據庫名稱能夠輸入以下代碼查詢全部數據庫名稱:"show dbs" 命令能夠顯示全部數據的列表shell
show dbs
查看數據庫中的集合名:數據庫
show collections
結果如圖所示:
下表列出了 RDBMS 與 MongoDB 對應的術語:
json
insert函數可將一個文檔插入到集合中去。以一個博客舉例。先建立一個叫post的變量(JavaScript對象)有三個鍵和對應的屬性。插入代碼:數組
db.blog.insert(post)
如圖所示:
批量插入bash
db.blog.insertMany([{"_id":0},{"_id":1},{"_id":2}])
查詢代碼以下:
db.blog.find()
如圖所示:
多出來的"_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';
若是給博客新增一個評論功能,則須要新增key-value,用於保存評論數組。
post.comments = []
以後用新版本的文檔替換舊版本:
db.blog.update({"title":"My Blog Post"},post)
"$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"})
刪除整個集合用drop()
db.blog.drop()
MongoDB使用 ensureIndex() 方法來建立索引。
db.COLLECTION_NAME.ensureIndex({KEY:1})
語法中 Key 值爲你要建立的索引字段,1爲指定按升序建立索引,若是你想按降序來建立索引指定爲-1便可。
固然也能夠給多個字段創建索引
db.col.ensureIndex({"title":1,"description":-1})
MongoDB的聚合管道將MongoDB文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。
表達式:處理輸入文檔並輸出。表達式是無狀態的,只能用於計算當前聚合管道的文檔,不能處理其它的文檔。
這裏咱們介紹一下聚合框架中經常使用的幾個操做:
db.article.aggregate( { $project : { title : 1 , author : 1 , }} );
db.articles.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] );
db.article.find().limit
db.article.aggregate( { $skip : 5 });
$group:將集合中的文檔分組,可用於統計結果。
$sort:將輸入文檔排序後輸出。
鏈接數據庫,你須要指定數據庫名稱,若是指定的數據庫不存在,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()); }