MongoDB 試用

部分內容摘自 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安裝簡單。

下載

下載官網:https://www.mongodb.com/download-center
對於ubuntu15.10,可以下載使用:mongodb-linux-x86_64-ubuntu1404-3.4.0,tar.gz文件解壓可用。

啓動

執行mongo安裝目錄中的bin目錄執行mongod命令來啓動mongdb服務,注意,如果你的數據庫目錄不是/data/db,可以通過 --dbpath 來指定:

 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。


深入學習

在shell交互窗口,執行 show dbs,顯示所有數據庫,執行 db 顯示當前使用的數據庫,運行"use"命令,可以連接到一個指定的數據庫(如果不存在會自動創建,注意:只有在插入一些文檔後show dbs才能看到use創建的數據庫,db.dropDatabase()可刪除當前數據庫)。

在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 正則表達式類型。用於存儲正則表達式。

文檔數據更新實例

只更新第一條記錄:

db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );

全部更新:

db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );

只添加第一條:

db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );

全部添加加進去:

db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );

全部更新:

db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true );

只更新第一條記錄:

db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );

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 驅動。
網址:http://mongodb.github.io/mongo-java-driver/
<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集合中。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章