部分內容摘自 http://www.runoob.com/mongodb/mongodb-tutorial.html
什麼是MongoDB ?
MongoDB 是由C++語言編寫的,是一個基於分佈式文件存儲的開源數據庫系統。
在高負載的情況下,添加更多的節點,可以保證服務器性能。
MongoDB 旨在爲WEB應用提供可擴展的高性能數據存儲解決方案。
MongoDB 將數據存儲爲一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔類似於 JSON 對象。字段值可以包含其他文檔,數組及文檔數組。
主要特點
- MongoDB的提供了一個面向文檔存儲,操作起來比較簡單和容易。
- 你可以在MongoDB記錄中設置任何屬性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")來實現更快的排序。
- 你可以通過本地或者網絡創建數據鏡像,這使得MongoDB有更強的擴展性。
- 如果負載的增加(需要更多的存儲空間和更強的處理能力) ,它可以分佈在計算機網絡中的其他節點上這就是所謂的分片。
- Mongo支持豐富的查詢表達式。查詢指令使用JSON形式的標記,可輕易查詢文檔中內嵌的對象及數組。
- MongoDb 使用update()命令可以實現替換完成的文檔(數據)或者一些指定的數據字段 。
- Mongodb中的Map/reduce主要是用來對數據進行批量處理和聚合操作。
- Map和Reduce。Map函數調用emit(key,value)遍歷集合中所有的記錄,將key與value傳給Reduce函數進行處理。
- Map函數和Reduce函數是使用Javascript編寫的,並可以通過db.runCommand或mapreduce命令來執行MapReduce操作。
- GridFS是MongoDB中的一個內置功能,可以用於存放大量小文件。
- MongoDB允許在服務端執行腳本,可以用Javascript編寫某個函數,直接在服務端執行,也可以把函數的定義存儲在服務端,下次直接調用即可。
- MongoDB支持各種編程語言:RUBY,PYTHON,JAVA,C++,PHP,C#等多種語言。
- MongoDB安裝簡單。
下載
啓動
cd /home/conquer/mine/soft/mongodb-linux-x86_64-ubuntu1404-3.4.0/bin
./mongod --dbpath=/home/conquer/mine/work_space/mongo--dbpath
官方README
COMPONENTS
bin/mongod - The database process.
bin/mongos - Sharding controller.
bin/mongo - The database shell (uses interactive javascript).
UTILITIES
bin/mongodump - MongoDB dump tool - for backups, snapshots, etc..
bin/mongorestore - MongoDB restore a dump
bin/mongoexport - Export a single collection to test (JSON, CSV)
bin/mongoimport - Import from JSON or CSV
bin/mongofiles - Utility for putting and getting files from MongoDB GridFS
bin/mongostat - Show performance statistics
RUNNING
For command line options invoke:
$ ./mongod --help
To run a single server database:
$ mkdir /data/db
$ ./mongod
$
$ # The mongo javascript shell connects to localhost and test database by default:
$ ./mongo
> help
DRIVERS
Client drivers for most programming languages are available at mongodb.org. Use the
shell ("mongo") for administrative tasks.
DOCUMENTATION
http://www.mongodb.org/
後臺管理 Shell
如果你需要進入MongoDB後臺管理,你需要先打開mongodb裝目錄的下的bin目錄,然後執行mongo命令,
MongoDB Shell是MongoDB自帶的交互式Javascript shell,用來對MongoDB進行操作和管理的交互式環境:
$ ./mongo ……
由於它是一個JavaScript shell,您可以運行一些簡單的算術運算:
> 2+2 4 > 3+6 9
插入數據
> db.mydb.insert({a:1,b:2});
WriteResult({ "nInserted" : 1 })
> db.mydb.find()
{ "_id" : ObjectId("58462273610c6eebe8b258fd"), "a" : 1, "b" : 2 }
MongoDb web 用戶界面
MongoDB 提供了簡單的 HTTP 用戶界面。 如果你想啓用該功能,需要在啓動的時候指定參數 --rest 。
$ ./mongod --dbpath=/data/db --rest
MongoDB 的 Web 界面訪問端口比服務的端口多1000。
如果你的MongoDB運行端口使用默認的27017,你可以在端口號爲28017訪問web用戶界面,即地址爲:http://localhost:28017。
深入學習
在mongodb中基本的概念是文檔、集合、數據庫,下表將幫助您更容易理解Mongo中的一些概念:
SQL術語/概念 | MongoDB術語/概念 | 解釋/說明 |
---|---|---|
database | database | 數據庫 |
table | collection | 數據庫表/集合 |
row | document | 數據記錄行/文檔 |
column | field | 數據字段/域 |
index | index | 索引 |
table joins | 表連接,MongoDB不支持 | |
primary key | primary key | 主鍵,MongoDB自動將_id字段設置爲主鍵 |
集合就是 MongoDB 文檔組,類似於 RDBMS (關係數據庫管理系統:Relational Database Management System)中的表格。
集合存在於數據庫中,集合沒有固定的結構,這意味着你在對集合可以插入不同格式和類型的數據,但通常情況下我們插入集合的數據都會有一定的關聯性。
比如,我們可以將以下不同數據結構的文檔插入到集合中:
{"site":"www.baidu.com"} {"site":"www.google.com","name":"Google"} {"site":"www.runoob.com","name":"菜鳥教程","num":5}
當第一個文檔插入時,集合就會被創建,刪除一個集合(包括集合中的文檔),使用:db.collection.drop()
MongoDB中常用的幾種數據類型。
數據類型 | 描述 |
---|---|
String | 字符串。存儲數據常用的數據類型。在 MongoDB 中,UTF-8 編碼的字符串纔是合法的。 |
Integer | 整型數值。用於存儲數值。根據你所採用的服務器,可分爲 32 位或 64 位。 |
Boolean | 布爾值。用於存儲布爾值(真/假)。 |
Double | 雙精度浮點值。用於存儲浮點值。 |
Min/Max keys | 將一個值與 BSON(二進制的 JSON)元素的最低值和最高值相對比。 |
Arrays | 用於將數組或列表或多個值存儲爲一個鍵。 |
Timestamp | 時間戳。記錄文檔修改或添加的具體時間。 |
Object | 用於內嵌文檔。 |
Null | 用於創建空值。 |
Symbol | 符號。該數據類型基本上等同於字符串類型,但不同的是,它一般用於採用特殊符號類型的語言。 |
Date | 日期時間。用 UNIX 時間格式來存儲當前日期或時間。你可以指定自己的日期時間:創建 Date 對象,傳入年月日信息。 |
Object ID | 對象 ID。用於創建文檔的 ID。 |
Binary Data | 二進制數據。用於存儲二進制數據。 |
Code | 代碼類型。用於在文檔中存儲 JavaScript 代碼。 |
Regular expression | 正則表達式類型。用於存儲正則表達式。 |
文檔數據更新實例
只更新第一條記錄:
全部更新:
只添加第一條:
全部添加加進去:
全部更新:
只更新第一條記錄:
MongoDB 查詢文檔
語法
MongoDB 查詢數據的語法格式如下:
>db.COLLECTION_NAME.find()
find() 方法以非結構化的方式來顯示所有文檔。
如果你需要以易讀的方式來讀取數據,可以使用 pretty() 方法,語法格式如下:
>db.col.find().pretty()
pretty() 方法以格式化的方式來顯示所有文檔。
實例
以下實例我們查詢了集合 col 中的數據:
> db.col.find().pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
除了 find() 方法之外,還有一個 findOne() 方法,它只返回一個文檔。
MongoDB 與 RDBMS Where 語句比較
如果你熟悉常規的 SQL 數據,通過下表可以更好的理解 MongoDB 的條件語句查詢:
操作 | 格式 | 範例 | RDBMS中的類似語句 |
---|---|---|---|
等於 |
{<key>:<value> } |
db.col.find({"by":"菜鳥教程"}).pretty() |
where by = '菜鳥教程' |
小於 |
{<key>:{$lt:<value>}} |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
小於或等於 |
{<key>:{$lte:<value>}} |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
大於 |
{<key>:{$gt:<value>}} |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
大於或等於 |
{<key>:{$gte:<value>}} |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
不等於 |
{<key>:{$ne:<value>}} |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
MongoDB AND 條件
MongoDB 的 find() 方法可以傳入多個鍵(key),每個鍵(key)以逗號隔開,及常規 SQL 的 AND 條件。
語法格式如下:
>db.col.find({key1:value1, key2:value2}).pretty()
實例
以下實例通過 by 和 title 鍵來查詢 菜鳥教程 中 MongoDB 教程 的數據
> db.col.find({"by":"菜鳥教程", "title":"MongoDB 教程"}).pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
以上實例中類似於 WHERE 語句:WHERE by='菜鳥教程' AND title='MongoDB 教程'
MongoDB OR 條件
MongoDB OR 條件語句使用了關鍵字 $or,語法格式如下:
>db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()
實例
以下實例中,我們演示了查詢鍵 by 值爲 菜鳥教程 或鍵 title 值爲 MongoDB 教程 的文檔。
>db.col.find({$or:[{"by":"菜鳥教程"},{"title": "MongoDB 教程"}]}).pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } >
AND 和 OR 聯合使用
以下實例演示了 AND 和 OR 聯合使用,類似常規 SQL 語句爲: 'where likes>50 AND (by = '菜鳥教程' OR title = 'MongoDB 教程')'
>db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鳥教程"},{"title": "MongoDB 教程"}]}).pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
MongoDB Java
在 Java 程序中如果要使用 MongoDB,你需要確保已經安裝了 Java 環境及 MongoDB JDBC 驅動。<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
java示例代碼:
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class JDBCDriverTest {
public static void main(String[] args) {
try {
//連接到MongoDB服務 如果是遠程連接可以替換“localhost”爲服務器所在IP地址
//ServerAddress()兩個參數分別爲 服務器地址 和 端口
// ServerAddress serverAddress = new ServerAddress("localhost",27017);
// List<ServerAddress> addrs = new ArrayList<ServerAddress>();
// addrs.add(serverAddress);
//
// //MongoCredential.createScramSha1Credential()三個參數分別爲 用戶名 數據庫名稱 密碼
// MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
// List<MongoCredential> credentials = new ArrayList<MongoCredential>();
// credentials.add(credential);
//
// //通過連接認證獲取MongoDB連接
// MongoClient mongoClient = new MongoClient(addrs,credentials);
//默認無需要密碼,連接到數據庫
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
System.out.println("Connect to database successfully");
// mongoDatabase.createCollection("test");
// System.out.println("集合創建成功");
// 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("文檔插入成功");
//更新文檔 將文檔中likes=100的文檔修改爲likes=200
// collection.updateMany(Filters.eq("likes", 100), new Document("$set",new Document("likes",200)));
//刪除符合條件的第一個文檔
// collection.deleteOne(Filters.eq("likes", 200));
// //刪除所有符合條件的文檔
// collection.deleteMany (Filters.eq("likes", 200));
MongoCursor<String> iterator = mongoDatabase.listCollectionNames().iterator();
while (iterator.hasNext()) {
String cName = iterator.next();
System.out.println("集合: " + cName);
MongoCollection<Document> collection = mongoDatabase.getCollection(cName);
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
System.out.println(mongoCursor.next());
}
}
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
}
MongoDB Map Reduce
Map-Reduce是一種計算模型,簡單的說就是將大批量的工作(數據)分解(MAP)執行,然後再將結果合併成最終結果(REDUCE)。
MongoDB提供的Map-Reduce非常靈活,對於大規模數據分析也相當實用。
MapReduce 命令
以下是MapReduce的基本語法:
>db.collection.mapReduce( function() {emit(key,value);}, //map 函數 function(key,values) {return reduceFunction}, //reduce 函數 { out: collection, query: document, sort: document, limit: number } )
使用 MapReduce 要實現兩個函數 Map 函數和 Reduce 函數,Map 函數調用 emit(key, value), 遍歷 collection 中所有的記錄, 將key 與 value 傳遞給 Reduce 函數進行處理。
Map 函數必須調用 emit(key, value) 返回鍵值對。
參數說明:
- map :映射函數 (生成鍵值對序列,作爲 reduce 函數參數)。
- reduce 統計函數,reduce函數的任務就是將key-values變成key-value,也就是把values數組變成一個單一的值value。。
- out 統計結果存放集合 (不指定則使用臨時集合,在客戶端斷開後自動刪除)。
- query 一個篩選條件,只有滿足條件的文檔纔會調用map函數。(query。limit,sort可以隨意組合)
- sort 和limit結合的sort排序參數(也是在發往map函數前給文檔排序),可以優化分組機制
- limit 發往map函數的文檔數量的上限(要是沒有limit,單獨使用sort的用處不大)
使用 MapReduce
考慮以下文檔結構存儲用戶的文章,文檔存儲了用戶的 user_name 和文章的 status 字段:
>db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"active" }) WriteResult({ "nInserted" : 1 })
現在,我們將在 posts 集合中使用 mapReduce 函數來選取已發佈的文章(status:"active"),並通過user_name分組,計算每個用戶的文章數:
>db.posts.mapReduce( function() { emit(this.user_name,1); }, function(key, values) {return Array.sum(values)}, { query:{status:"active"}, out:"post_total" } )
以上 mapReduce 輸出結果爲:
{ "result" : "post_total", "timeMillis" : 23, "counts" : { "input" : 5, "emit" : 5, "reduce" : 1, "output" : 2 }, "ok" : 1 }
結果表明,共有4個符合查詢條件(status:"active")的文檔, 在map函數中生成了4個鍵值對文檔,最後使用reduce函數將相同的鍵值分爲兩組。
具體參數說明:
- result:儲存結果的collection的名字,這是個臨時集合,MapReduce的連接關閉後自動就被刪除了。
- timeMillis:執行花費的時間,毫秒爲單位
- input:滿足條件被髮送到map函數的文檔個數
- emit:在map函數中emit被調用的次數,也就是所有集合中的數據總量
- ouput:結果集合中的文檔個數(count對調試非常有幫助)
- ok:是否成功,成功爲1
- err:如果失敗,這裏可以有失敗原因,不過從經驗上來看,原因比較模糊,作用不大
使用 find 操作符來查看 mapReduce 的查詢結果:
>db.posts.mapReduce( function() { emit(this.user_name,1); }, function(key, values) {return Array.sum(values)}, { query:{status:"active"}, out:"post_total" } ).find()
以上查詢顯示如下結果,兩個用戶 tom 和 mark 有兩個發佈的文章:
{ "_id" : "mark", "value" : 4 } { "_id" : "runoob", "value" : 1 }
用類似的方式,MapReduce可以被用來構建大型複雜的聚合查詢。
Map函數和Reduce函數可以使用 JavaScript 來實現,使得MapReduce的使用非常靈活和強大。
MongoDB GridFS
GridFS 用於存儲和恢復那些超過16M(BSON文件限制)的文件(如:圖片、音頻、視頻等)。
GridFS 也是文件存儲的一種方式,但是它是存儲在MonoDB的集合中。
GridFS 可以更好的存儲大於16M的文件。
GridFS 會將大文件對象分割成多個小的chunk(文件片段),一般爲256k/個,每個chunk將作爲MongoDB的一個文檔(document)被存儲在chunks集合中。
GridFS 用兩個集合來存儲一個文件:fs.files與fs.chunks。
每個文件的實際內容被存在chunks(二進制數據)中,和文件有關的meta數據(filename,content_type,還有用戶自定義的屬性)將會被存在files集合中。