MongoDB**是一種面向文檔的數據庫管理系統,由C++語言編寫的,是一個基於分佈式文件存儲的開源數據庫系統。2007年10月,MongoDB由10gen團隊所發展。2009年2月首度推出。在高負載的狀況下,添加更多的節點,能夠保證服務器性能。MongoDB 旨在爲WEB應用提供可擴展的高性能數據存儲解決方案。MongoDB 將數據存儲爲一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔相似於 JSON 對象。字段值能夠包含其餘文檔,數組及文檔數組。php
優勢java
缺點mysql
解壓下載https://www.mongodb.com/download-center/community的ZIP包,並更改文件名爲mongodb,在其同目錄下建立文件夾data和data\db,log和mongo.log。git
mongod --dbpath D:\mongodb\data\db --logpath=D:\mongodb\log\mongodb.log --logappend
最後,再次打開cmd 進入cd mongodb\bin,執行下面命令:mongogithub
在瀏覽器中打開地址:正則表達式
用戶名和密碼鏈接到MongoDB,'username:password@hostname/dbname'sql
易懂的讀取pretty(),mongodb
db.collection.remove( <query>, <justOne> )
db.col.find({key1:value1, key2:value2}).pretty()
>db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()
db.COLLECTION_NAME.find().limit(NUMBER)
skip()方法來跳過指定數量的數據,skip方法一樣接受一個數字參數做爲跳過的記錄條數。docker
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
db.COLLECTION_NAME.find().sort({KEY:1})
db.COLLECTION_NAME.ensureIndex({KEY:1})
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
mongod --port 27017 --dbpath D:\mongodb\data\db --logpath=D:\mongodb\log\mongodb.log --replSet rs0
以上實例會啓動一個名爲rs0的MongoDB實例,其端口號爲27017。shell
啓動後打開命令提示框並鏈接上mongoDB服務。
在Mongo客戶端使用命令rs.initiate()來啓動一個新的副本集。
咱們可使用rs.conf()來查看副本集的配置
查看副本集姿態使用 rs.status() 命令
D:\mongodb\bin>mongo MongoDB shell version v4.1.11-262-gc237f4c connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("7109348e-cade-4128-af30-7cf8776302a9") } MongoDB server version: 4.1.11-262-gc237f4c # 添加副本集 > rs.add("mongod1.net:27017") 2019-05-30T18:57:26.058-0700 E QUERY [js] uncaught exception: Error: assert failed : no config object retrievable from local.system.replset : doassert@src/mongo/shell/assert.js:20:14 assert@src/mongo/shell/assert.js:152:9 rs.add@src/mongo/shell/utils.js:1441:5 @(shell):1:1 # 查看當前運行是不是主節點 > db.isMaster() { "ismaster" : false, "secondary" : false, "info" : "Does not have a valid replica set config", "isreplicaset" : true, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : ISODate("2019-05-31T01:57:40.632Z"), "logicalSessionTimeoutMinutes" : 30, "connectionId" : 1, "minWireVersion" : 0, "maxWireVersion" : 8, "readOnly" : false, "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(0, 0), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(0, 0) } # 啓動一個新的副本集 > rs.initiate() # 查看副本集的配置 rs0:SECONDARY> rs.conf() # 查看副本集姿態 rs0:PRIMARY> rs.status()
MongoDB數據備份:mongodbdump
使用mongodump命令來備份MongoDB數據。該命令能夠導出全部數據到指定目錄中。mongodump命令能夠經過參數指定導出的數據量級轉存的服務器。
、
mongostat 和 mongotop 兩個命令來監控MongoDB的運行狀況。
環境配置,在Java程序中若是要使用MongoDB,你須要確保已經安裝了Java環境及MongoDB JDBC 驅動。
import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.WriteConcern; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBCursor; import com.mongodb.ServerAddress; import java.util.Arrays; public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到 mongodb 服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到 mongodb 服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.createCollection("mycol"); System.out.println("Collection created successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到 mongodb 服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.createCollection("mycol"); System.out.println("Collection created successfully"); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到 mongodb 服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); BasicDBObject doc = new BasicDBObject("title", "MongoDB"). append("description", "database"). append("likes", 100). append("url", "//www.w3cschool.cn/mongodb/"). append("by", "w3cschool.cn"); coll.insert(doc); System.out.println("Document inserted successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到 mongodb 服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBCursor cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Inserted Document: "+i); System.out.println(cursor.next()); i++; } }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到Mongodb服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到你的數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBCursor cursor = coll.find(); while (cursor.hasNext()) { DBObject updateDocument = cursor.next(); updateDocument.put("likes","200") coll.update(updateDocument); } System.out.println("Document updated successfully"); cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Updated Document: "+i); System.out.println(cursor.next()); i++; } }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 鏈接到Mongodb服務 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 鏈接到你的數據庫 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBObject myDoc = coll.findOne(); coll.remove(myDoc); DBCursor cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Inserted Document: "+i); System.out.println(cursor.next()); i++; } System.out.println("Document deleted successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
MongoDB 的關係表示多個文檔之間在邏輯上的相互聯繫。文檔間能夠經過嵌入和引用來創建聯繫。MongoDB 中的關係能夠是:
一個用戶能夠有多個地址,因此是一對多的關係。
"_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }] }
數據保存在單一文檔中,比較容易的獲取很維護數據。 你能夠這樣查詢用戶的地址:
>db.users.findOne({"name":"Tom Benzamin"},{"address":1})
這種數據結構的缺點是,若是用戶和用戶地址在不斷增長,數據量不斷變大,會影響讀寫性能。
{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ] }
須要兩次查詢,第一次查詢用戶地址的對象id(ObjectId),第二次經過查詢的id獲取用戶的詳細地址信息。
>var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) >var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})
考慮如下 posts 集合的文檔數據,包含了文章內容(post_text)及標籤(tags):
{ "post_text": "enjoy the mongodb articles on w3cschool.cn", "tags": [ "mongodb", "w3cschool" ] }
咱們能夠對 post_text 字段創建全文索引,這樣咱們能夠搜索文章內的內容:
>db.posts.ensureIndex({post_text:"text"})
如今咱們已經對 post_text 創建了全文索引,咱們能夠搜索文章中的關鍵詞w3cschool.cn:
>db.posts.find({$text:{$search:"w3cschool.cn"}})
如下命令返回了以下包含NoSQL關鍵詞的文檔數據:
D:\mongodb\bin>mongo MongoDB shell version v4.1.11-262-gc237f4c > show dbs admin 0.000GB config 0.000GB local 0.000GB myinfo 0.000GB w3cschooldb 0.000GB youj 0.000GB > use youj switched to db youj > db.col.find() { "_id" : ObjectId("5cef550377781c00a00de949"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } { "_id" : ObjectId("5cef690677781c00a00de94a"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } > db.col.ensureIndex({description:"text"}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } > db.col.find({$text:{$search:"NoSQL"}}) { "_id" : ObjectId("5cef690677781c00a00de94a"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } { "_id" : ObjectId("5cef550377781c00a00de949"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } >
刪除已存在的全文索引,可使用 find 命令查找索引名:
>db.col.getIndexes()
經過以上命令獲取索引名,本例的索引名爲post_text_text,執行如下命令來刪除索引:
> db.col.dropIndex('description_text')
使用 $regex 操做符來設置匹配字符串的正則表達式。
>db.posts.find({post_text:{$regex:"w3cschool.cn"}})
以上查詢也能夠寫爲:
>db.posts.find({post_text:/w3cschool.cn/})
若是檢索須要不區分大小寫,咱們能夠設置 $options 爲 $i。如下命令將查找不區分大小寫的字符串 w3cschool.cn:
>db.posts.find({post_text:{$regex:"w3cschool.cn",$options:"$i"}})
集合中會返回全部包含字符串 w3cschool.cn 的數據,且不區分大小寫:
{ "_id" : ObjectId("53493d37d852429c10000004"), "post_text" : "hey! this is my post on W3Cschool.cc", "tags" : [ "tutorialspoint" ] }
這在標籤的實現上很是有用,若是你須要查找包含以 tutorial 開頭的標籤數據(tutorial 或 tutorials 或 tutorialpoint 或 tutorialphp), 你可使用如下代碼:
>db.posts.find({tags:{$regex:"tutorial"}})
若是你的文檔中字段設置了索引,那麼使用索引相比於正則表達式匹配查找全部的數據查詢速度更快。
若是正則表達式是前綴表達式,全部匹配的數據將以指定的前綴字符串爲開始。例如: 若是正則表達式爲^tut ,查詢語句將查找以 tut 爲開頭的字符串。
GridFS 用於存儲和恢復那些超過16M(BSON文件限制)的文件(如:圖片、音頻、視頻等)。也是文件存儲的一種方式,可是它是存儲在MonoDB的集合中。GridFS 會將大文件對象分割成多個小的chunk(文件片斷),通常爲256k/個,每一個chunk將做爲MongoDB的一個文檔(document)被存儲在chunks集合中。
GridFS 用兩個集合來存儲一個文件:fs.files與fs.chunks。每一個文件的實際內容被存在chunks(二進制數據)中,和文件有關的meta數據(filename,content_type,還有用戶自定義的屬性)將會被存在files集合中。
如下是簡單的 fs.files 集合文檔:
{ "filename": "test.txt", "chunkSize": NumberInt(261120), "uploadDate": ISODate("2014-04-13T11:32:33.557Z"), "md5": "7b762939321e146569b07f72c62cca4f", "length": NumberInt(646) }
如下是簡單的 fs.chunks 集合文檔:
{ "files_id": ObjectId("534a75d19f54bfec8a2fe44b"), "n": NumberInt(0), "data": "Mongo Binary Data" }
如今咱們使用 GridFS 的 put 命令來存儲 mp3 文件。 調用 MongoDB 安裝目錄下bin的 mongofiles.exe工具。
打開命令提示符,進入到MongoDB的安裝目錄的bin目錄中,找到mongofiles.exe,並輸入下面的代碼:
>mongofiles.exe -d gridfs put song.mp3
GridFS 是存儲文件的數據名稱。若是不存在該數據庫,MongoDB會自動建立。Song.mp3 是音頻文件名。使用如下命令來查看數據庫中文件的文檔:
>db.fs.files.find()
以上命令執行後返回如下文檔數據:
{ _id: ObjectId('534a811bf8b4aa4d33fdf94d'), filename: "song.mp3", chunkSize: 261120, uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41", length: 10401959 }
咱們能夠看到 fs.chunks 集合中全部的區塊,如下咱們獲得了文件的 _id 值,咱們能夠根據這個 _id 獲取區塊(chunk)的數據:
>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})
以上實例中,查詢返回了 40 個文檔的數據,意味着mp3文件被存儲在40個區塊中。
MongoDB 沒有像 SQL 同樣有自動增加的功能, MongoDB 的id是系統自動生成的12字節惟一標識。但在某些狀況下,咱們可能須要實現 ObjectId 自動增加功能。因爲 MongoDB 沒有實現這個功能,咱們能夠經過編程的方式來實現,如下咱們將在 counters 集合中實現id字段自動增加。
如下 products 文檔。id 字段實現 從 1,2,3,4 到 n 的自動增加功能。
{ "_id":1, "product_name": "Apple iPhone", "category": "mobiles" }
爲此,建立 counters 集合,序列字段值能夠實現自動長:
>db.createCollection("counters")
向 counters 集合中插入如下文檔,使用 productid 做爲 key:
{ "_id":"productid", "sequence_value": 0 }
sequence_value 字段是序列經過自動增加後的一個值。使用如下命令插入 counters 集合的序列文檔中:
>db.counters.insert({_id:"productid",sequence_value:0})
建立函數 getNextSequenceValue 來做爲序列名的輸入, 指定的序列會自動增加 1 並返回最新序列值。在本文的實例中序列名爲 productid 。
>function getNextSequenceValue(sequenceName){ var sequenceDocument = db.counters.findAndModify( { query:{_id: sequenceName }, update: {$inc:{sequence_value:1}}, new:true }); return sequenceDocument.sequence_value; }
使用 getNextSequenceValue 函數建立一個新的文檔, 並設置文檔 _id 自動爲返回的序列值:
>db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Apple iPhone", "category":"mobiles"}) >db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Samsung S3", "category":"mobiles"})
使用 getNextSequenceValue 函數來設置 _id 字段。爲了驗證函數是否有效,咱們可使用如下命令讀取文檔:
>db.prodcuts.find()
以上命令將返回如下結果,咱們發現 _id 字段是自增加的:
{ "_id" : 1, "product_name" : "Apple iPhone", "category" : "mobiles"} { "_id" : 2, "product_name" : "Samsung S3", "category" : "mobiles" }