MongoDB學習總結(二)

            前言:學習札記!git

 

MongoDB學習總結(二)

1.  安裝、初識

 

以前寫過一篇MongoDB的快速上手文章,裏邊詳細的講了如何安裝、啓動MongoDB,這裏就再也不累述安裝過程,簡單介紹一下Mongodb的基本操做。正則表達式

打開命令行窗口,輸入「mongo」命令,默認會鏈接到test數據庫。sql

l  Insertmongodb

db.person.insert({"name":"Olive","age":18})數據庫

db.person.insert({"name":"Momo","age":17})編程

l  find數組

db.person.find()//查找全部的person數據安全

{ "_id" :ObjectId("58a03991d57e6773c574e485"), "name" :"Olive", "age" : 18 }服務器

{ "_id" :ObjectId("58a039a8d57e6773c574e486"), "name" :"Momo", "age" : 17 }架構

db.person.find({"name":"Olive"})//查找名爲Olive的person數據

{ "_id" :ObjectId("58a03991d57e6773c574e485"), "name" :"Olive", "age" : 18 }

u  "$gt","$gte", "$lt", "$lte", "$ne", "沒有特殊關鍵字"(對應的爲>,>=,<,<=,!=)

db.user.find({"age":{$gt:22}})//年齡大於22

{ "_id" : ObjectId("58a03dc7d57e6773c574e488"),"name" : "joe", "password" : "123456","age" : 25, "address" : { "province" :"henan", "city" : "zhengzhou" },"favourite" : [ "money", "girl" ] }

db.user.find({"age":{$lt:22}})//年齡小於22

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

db.user.find({"age":{$ne:25}})//年齡不等於25

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

u  "無關鍵字「, "$or", "$in","$nin"

db.user.find({$or:[{"name":"jack"},{"age":25}]})//名字爲jack或age爲25的user

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

{ "_id" :ObjectId("58a03dc7d57e6773c574e488"), "name" :"joe", "password" : "123456", "age" :25, "address" : { "province" : "henan","city" : "zhengzhou" }, "favourite" : ["money", "girl" ] }

db.user.find({"address.city":{$in:["chaoyang","zhengzhou"]}})//城市爲chaoyang或zhengzhou的user

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

{ "_id" :ObjectId("58a03dc7d57e6773c574e488"), "name" :"joe", "password" : "123456", "age" :25, "address" : { "province" : "henan","city" : "zhengzhou" }, "favourite" : ["money", "girl" ] }

db.user.find({"address.city":{$nin:["chaoyang1","zhengzhou"]}})//查找城市不是chaoyang1或不是zhengzhou的user

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

u  正則表達式匹配

db.user.find({$or:[{"name":/^j/},{"name":/e$/}]})//匹配名字以j開頭或者名字以e結尾的user

{ "_id" :ObjectId("58a03cc0d57e6773c574e487"), "name" :"jack", "password" : "123456", "age" :20, "address" : { "province" : "beijing","city" : "chaoyang" }, "favourite" : ["apple", "banana" ] }

{ "_id" :ObjectId("58a03dc7d57e6773c574e488"), "name" :"joe", "password" : "123456", "age" :25, "address" : { "province" : "henan","city" : "zhengzhou" }, "favourite" : ["money", "girl" ] }

u  $where

db.user.find({$where:function(){return this.name=="joe"}})//用$where的方式查詢名爲joe的user

{ "_id" :ObjectId("58a03dc7d57e6773c574e488"), "name" :"joe", "password" : "123456", "age" :25, "address" : { "province" : "henan","city" : "zhengzhou" }, "favourite" : ["money", "girl" ] }

 

l  Update

db.person.update({"name":"Olive"},{"name":"Olive116","age":19})//更新名爲Olive的person信息

u  $inc 修改器(自增$inc指定的值,若是「文檔」中沒有此key,則會建立key,局部修改)

db.user.update({"name":"jack"},{$inc:{"age":10}})

u  $set修改器(局部修改age值)

db.user.update({"name":"jack"},{$set:{"age":10}})

u upsert操做(若是沒有查到,就在數據庫裏面新增一條)

db.user.update({"name":"jackson"},{$inc:{"age":1}},true)//更新名爲jackson的age值,若是該user不存在,則新增一條user信息

u  批量更新

db.user.update({「name」:「hxf」},{$inc:{「age」:10}},true)//批量更新名爲hxf的user

l  remove

db.person.remove({"name":"Momo"})//移除名爲Momo的person信息

2.  聚合

2.1count

db.user.count({"age":25})//統計age爲25的user個數

2.2distinct

db.user.distinct("age")

2.3group

db.user.group({"key":{"age":true},"initial":{"person":[]},"$reduce":function(cur,prev){prev.person.push(cur.name);}})

key:  這個就是分組的key,咱們這裏是對年齡分組。

initial: 每組都分享一個」初始化函數「,特別注意:是每一組,好比這個的age=20的value的list分享一個initial函數,age=22一樣也分享一個initial函數。

$reduce: 這個函數的第一個參數是當前的文檔對象,第二個參數是上一次function操做的累計對象,第一次爲initial中的{」perosn「:[]}。有多少個文檔, $reduce就會調用多少次。

結果:

[

        {

                "age" : 10,

                "person" : [

                        "jack"

                ]

        },

        {

                "age" : 25,

                "person" : [

                        "joe"

                ]

        },

        {

                "age" : 1,

                "person" : [

                        "jackson"

                ]

        }

]

db.user.group({"key":{"age":true},"initial":{"person":[]},"reduce":function(doc,out){out.person.push(doc.name);},"finallize":function(out){out.count=out.person.length;},"condition":{"age":{$lt:25}}})

user數組裏面的人員太多,想加上一個count屬性標明一下。

 針對上面的需求,在group裏面仍是很好辦到的,由於group有這麼兩個可選參數: condition 和 finalize。

condition:  這個就是過濾條件。

finalize:這是個函數,每一組文檔執行完後,多會觸發此方法

結果:

[

        {

                "age" : 10,

                "person" : [

                        "jack"

                ]

        },

        {

                "age" : 1,

                "person" : [

                        "jackson"

                ]

        }

]

2.4mapReduce

mapReduce實際上是一種編程模型,用在分佈式計算中,其中有一個「map」函數,一個」reduce「函數。

l  map:

         這個稱爲映射函數,裏面會調用emit(key,value),集合會按照你指定的key進行映射分組。

l  reduce:

        這個稱爲簡化函數,會對map分組後的數據進行分組簡化,注意:在reduce(key,value)中的key就是

     emit中的key,vlaue爲emit分組後的emit(value)的集合,這裏也就是不少{"count":1}的數組。

l  mapReduce:

         這個就是最後執行的函數,參數爲map,reduce和一些可選參數

mapfunction(){ emit(this.name,{count:1});

reducefunction(key,value){ var result={count:0}; for(var i=0;i<value.length;i++){result.count+=value[i].count;}return result;}

db.user.mapReduce(map,reduce,{「output」:「collection」});

3.  遊標

Mongodb裏的遊標是申明一個查詢結構,並無出具體的數據,只有在遍歷時才加載過來,經過遊標讀取,枚舉完成以後銷燬遊標。

Varlist=db.user.find()

list.Foreach(function(item){print(item.name);});

同時在構造查詢時,還能夠根據須要進行復雜的查詢構造,例如:分頁、排序等

Varlist=db.user.find().sort({「name」,1}).skip(3).limit(3);

4.  索引

4.1 性能分析函數(explain)

在數據庫中插入10萬條數據,以下:

for(vari=0;i<1000000;i++) {

...var rand=parseInt(i*Math.random());

...db.user.insert({"name":"HXF"+i,"age":i})

... }

查找一條數據,並利用「explain」分析函數,進行查詢分析。

db.user.find({"name":"HXF9999"}).explain()

{

        "queryPlanner" : {

                "plannerVersion" : 1,

                "namespace" :"test.user",

                "indexFilterSet" :false,

                "parsedQuery" : {

                        "name" : {

                                "$eq": "HXF9999"

                        }

                },

                "winningPlan" : {

                        "stage" :"COLLSCAN",

                        "filter" : {

                               "name" : {

                                       "$eq" : "HXF9999"

                                }

                        },

                        "direction" :"forward"

                },

                "rejectedPlans" : [ ]

        },

        "serverInfo" : {

                "host" :"WIN-GJ07N56QAK7",

                "port" : 27017,

                "version" :"3.0.6",

                "gitVersion" :"1ef45a23a4c5e3480ac919b28afcba3c615488f2"

        },

        "ok" : 1

}

4.2 創建索引(ensureIndex)

db.user.ensureIndex({「name」:1});

利用ensureIndex方法爲name字段添加索引,「1」表示照name升序,「-1」表示照name降序。

db.user.find({name:「墨遙」}).explain();

4.3 惟一索引

db.user.ensureIndex({"name":1},{"unique":true})

建立惟一索引,重複的鍵就不能再插入。

4.4 組合索引

多條件查詢時,能夠經過建立組合索引來加速查詢。

db.user.ensureIndex({"name":1,"birthday":1})

建立組合索引,按照name升序,birthday升序。升序和降序的不一樣都會產生不一樣的索引。

咱們能夠經過getindexes來查看user下建立的全部索引。

db.user.getIndexes();

查詢優化器在作查詢時,會使用咱們創建的這些索引來建立查詢方案,若是某一個先執行完則其餘查詢方案被close掉,這種方案會被mongodb保存起來,固然若是非要用本身指定的查詢方案,這也是能夠的,在mongodb中給咱們提供了hint方法讓咱們能夠暴力執行。

db.user.find({name:‘HXF’,age:27}).hint({age:1,name:1});

4.5 刪除索引

db.user.dropIndex(「name_1」)

5.  主從複製

Mongodb主從複製的部署架構能夠實現數據的備份、數據恢復、讀寫分離。

部署實踐:

在一臺服務器上啓動Mongodb並將該數據庫指定爲主數據庫,命令以下:

mongod --dbpath D:\MangoDB\Data –master

在另外一臺服務器上啓動mongodb並將該數據庫指定爲從數據庫,命令以下:

mongod –dbpath E:\MongoDB\Data –-slave –source=主服務器IP:27017

動態的添加從屬服務器:

在新增的mongodb服務器上,使用local數據庫,並在sources中添加一個host

地址,以下:

在新的mongodb服務器上啓動mongodb數據庫,

use local

db.sources.insert({「host」:」主服務器Ip:端口」});//127.0.0.1:27017

l  讀寫分離

在從屬服務器中,執行rs.slaveOk()便可支持從從屬數據庫讀取信息

6.  副本集

副本集也是屬於主從集羣,可是跟上邊的集羣有區別的。

l  副本集的集羣沒有特定的主數據庫

l  若是某個主數據庫宕機了,集羣會自動推選一個從屬數據庫做爲主數據庫頂上,具有了自動故障恢復功能。

實踐以下:

建立集羣,啓動D盤的mongodb程序,指定端口2222,,其中集羣的名字爲HXFX,--replSet表示告知服務器HXFX集羣下還有其餘的數據庫(即指定的端口3333的數據庫)

mongod--dbpath D:\MongoDB\Data --port 2222 --replSet HXFX/127.0.0.1:3333

打開端口爲3333的數據庫

mongod--dbpath D:\SubMongoDB\Data --port 3333 --replSet HXFX/127.0.0.1:2222

 

鏈接到任意一臺服務器,並以admin登陸數據庫,進行副本集的初始化,命令以下:

mongo127.0.0.1:2222/admin

 

rs.runCommand({"replSetInitiate":{"_id":"HXFX"},"members":[{"_id":1,"host":"127.0.0.1:2222"},{"_id":2,"host":"127.0.0.1:3333"}]}})

 

新增一臺服務器,做爲仲裁服務器,以下:

mongod--dbpath D:\ThreeMongoDB\Data --port 4444 --replSet HXFX/127.0.0.3:2222

 

而後咱們在admin集合中使用rs.addArb()追加便可。以下:

rs.addArb("127.0.0.1:4444")

 

7.  分片

當數據量達到T級別的時候,mongodb採用將集合進行拆分,將拆分的數據分攤到幾個片上。咱們要了解」片鍵「的概念,也就是說拆分集合的依據是,按照鍵值進行拆分集合。這裏須要一個路由服務器(mongos),根據管理員設置的「片鍵」將數據分攤到本身管理的mongod集羣,同時須要一個config服務器,用來保存數據和片的對應關係以及相應的配置信息。同時還須要若干的mongodb服務器。具體實踐以下:

7.1 開啓config服務器

Config服務主要用來存儲數據和片的對應關係,所應該最早開啓。

--開啓Config服務器

mongod --dbpath D:\SubMongoDB\Data --port 2222

7.2 開啓mongos服務器

Mongos服務器就是一個路由服務器,同時要爲其指定config服務器

--開啓mongos服務器

mongos --port 3333 --configdb 127.0.0.1:2222

7.3 添加mongodb服務器(也就是要添加的片)

--啓動mongod服務器(4444,5555)

mongod --dbpath D:\ThreeMongoDB\Data --port 4444

 

mongod --dbpath D:\FourMongoDB\Data --port 5555

7.4 鏈接到mongos服務器並將mongodb服務添加分片

--鏈接到mongods服務器並將(4444,5555)服務器添加分片

mongo 127.0.0.1:3333/admin

 

db.runCommand({"addshard":"127.0.0.1:4444",allowLocal:true})

 

db.runCommand({"addshard":"127.0.0.1:5555",allowLocal:true})

 

7.5 mongos服務器設置片鍵切分數據

--開啓數據庫的分片功能

mongo 127.0.0.1:3333/admin

db.runCommand({"enablesharding":"test"})—爲test數據開啓分片功能

--指定集合中分片的鍵

db.runCommand({"shardcollection":"test.user","key":{"name":1}})—指定test數據庫中user集合的name爲片鍵

7.6 插入數據,查看效果

經過mongos向mongodb中插入10w數據,並經過db.printShardingStatus()來查看效果

 

 

插入的1萬條數據分佈在4444和5555服務器上。

8.  安裝部署

Mongod –dbpath D:\MongoDB\Data –-logpath D:\MongoDB\Log\log.txt–port 2222 –install

設置MongoDB數據存儲路徑,日誌路徑,同時開啓了安裝服務寄宿。

9.  狀態監控

經過db.serverStatus()來查看服務器的統計信息(全局鎖、索引、用戶操做行爲等)

經過mongostat實時刷新,觀看數據實時變化。

Mongostat –port 3333

10.          安全認證

Use admin

Db.system.users.remove({「user」:」XXX」})

 

11.          備份和恢復

Mongodump和mongorestore內置工具,保證不關閉服務器仍能copy數據。使用以下:

Mongodump -–port2222 –d test –o D:\MongoDB\Backup

將test數據庫備份到D盤的mongoDB文件夾下的Backup文件夾下

Mongorestore–-port 2222 –d test –-drop  D:\MongoDB\Backup\test

將D:\MongoDB\Backup\test還原到test數據庫,並刪除備份文件

經過加鎖和釋放鎖的方式保證數據,可以所有的備份下來

 db.runCommand({"fsync":1,"lock":1})

 釋放鎖: db.$cmd.unlock.findOne()

12.          驅動示例

官網驅動示例:(從官網下載Mongodb.net 的驅動)

App.config內容:

<configuration>

    <startup>

       <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>

    </startup>

  <appSettings><!—配置鏈接字符串、數據庫-->

    <add key="ConnString" value="mongodb://127.0.0.1:27017"/>

    <add key="DataBase" value="HXFDB"/>

  </appSettings>

</configuration>

 

    public staticclass MongoDBFactory

    {

        privatestatic string conn = ConfigurationManager.AppSettings["ConnString"];

        privatestatic string database = ConfigurationManager.AppSettings["DataBase"];

        private static MongoClient client = new MongoClient(conn);

        privatestatic MongoServer server = client.GetServer();

        privatestatic MongoDatabase db = server.GetDatabase(database);

        //增       

public static void Insert(string name)

        {

           MongoCollection collection = db.GetCollection("User");

           User user = new User() { ID = 0, Name = name, Sex = "男", Age = 27, Code = "MY001" , _id=newBson.ObjectId()};

           collection.Insert<User>(user);

 

           QueryDocument query = new QueryDocument { { "Name", name } };

           var list = collection.FindAs<User>(query);

          

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

        }

        //改

        publicstatic void Update1(string name)

        {

           MongoCollection collection = db.GetCollection("User");

           QueryDocument query = new QueryDocument { {"Name",name}};

           IMongoUpdate update = Update.Set("Code", "Olive001");

            collection.Update(query,update);

           var list = collection.FindAllAs<User>();

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

        }

        //刪

        publicstatic void Remove(string name)

        {

           MongoCollection collection = db.GetCollection("User");

           QueryDocument query = new QueryDocument { { "Name", name } };

           collection.Remove(query);

           var list = collection.FindAllAs<User>();

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

        }

        //查

        publicstatic void Query()

        {

           MongoCollection collection = db.GetCollection("User");

           Console.WriteLine("SELECT * FROM table ");

            //SELECT * FROM table

           var list = collection.FindAllAs<User>();

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

           Console.WriteLine("SELECT * FROM table WHERE Uid > 10 AND Uid< 20");

           // sql : SELECT * FROM table WHERE Uid > 10 AND Uid < 20

           QueryDocument query = new QueryDocument { };

           BsonDocument bd=new BsonDocument ();

           bd.Add("$gte",0);

           bd.Add("$lt",5);

           query.Add("ID", bd);

           list = collection.FindAs<User>(query);

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

           Console.WriteLine("SELECT Name FROM table WHERE Uid > 10 AND Uid< 20");

           // SELECT Name FROM table WHERE Uid > 10 AND Uid < 20

           FieldsDocument f = new FieldsDocument();

           f.Add("Name", 1);

           list = collection.FindAs<User>(query).SetFields(f);

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}", u.Name);

           }

           Console.WriteLine("SELECT * FROM table ORDER BY Uid DESC LIMIT10,10");

           //SELECT * FROM table ORDER BY Name DESC LIMIT 10,10

           SortByDocument s = new SortByDocument();

           s.Add("Name", -1);

           list = collection.FindAs<User>(query).SetSortOrder(s).SetSkip(1).SetLimit(10);

           foreach (var u in list)

           {

               Console.WriteLine("Name: {0}, Sex: {1}, Age: {2}, Code: {3}", u.Name,u.Sex, u.Age, u.Code);

           }

        }

    }

}

相關文章
相關標籤/搜索