MongoDB常用指令

MongoDB是一種強(qiáng)大、靈活、可擴(kuò)展的數(shù)據(jù)存儲形式。他是面向文檔的數(shù)據(jù)庫,是NoSQL的一種。它擴(kuò)展了關(guān)系型數(shù)據(jù)庫的眾多有用功能,如輔助索引、范圍查詢、和排序。還內(nèi)置了對MapReduce式聚合的支持,以及對地理空間索引的支持。由于它放棄了關(guān)系型數(shù)據(jù)庫“行”的概念,獲得了更加方便的擴(kuò)展性。面向文檔的方式可以將文檔或數(shù)組內(nèi)嵌進(jìn)來,所以用一條記錄就可以表示很復(fù)雜的層次關(guān)系。

MongoDB沒有模式,文檔的鍵不會事先定義也不會固定不變。

MongoDB從設(shè)計(jì)之初,就考慮了擴(kuò)展的問題。他所采用的面向文檔的數(shù)據(jù)模型使之可以自動在多臺服務(wù)器之間分割數(shù)據(jù)。它還可以平衡集群的數(shù)據(jù)和負(fù)載,自動重排文檔。如果需要更大的容量時,只需要向集群中增加新機(jī)器,數(shù)據(jù)庫就會自動幫我們處理剩下的事情。

文檔是MongoDB的核心概念。多個鍵及其相關(guān)聯(lián)的值有序的放在一起就是文檔。MongoDB不但飯區(qū)分類型,還區(qū)分大小寫。

集合collection就是一組文檔。MongoDB中的文檔有點(diǎn)類似關(guān)系型數(shù)據(jù)庫中的行,集合有點(diǎn)類似于關(guān)系型數(shù)據(jù)庫中的表。但是與關(guān)系型數(shù)據(jù)庫不同的是,MongoDB的集合是沒有模式的。但是在同一個集合中使用多種模式,不管對于開發(fā)者還是管理者,都是一個噩夢。所以我們會使用多個集合。將同種類型的文檔放在同一個集合,數(shù)據(jù)會更加集中,可以節(jié)省查詢時間,創(chuàng)建索引時也可以變得十分高效。多個集合可以使我們的查詢更加便捷,我們不需要從所有的數(shù)據(jù)中找我們需要的,只需要去相應(yīng)的集合中查詢就可以了。

常用指令

1.創(chuàng)建數(shù)據(jù)庫

MongoDB不需要專門的創(chuàng)建數(shù)據(jù)庫語句,直接使用use DataBaseName命令,如果數(shù)據(jù)庫存在,則使用該數(shù)據(jù)庫。如果該數(shù)據(jù)庫不存在,則新建該數(shù)據(jù)庫。

> use newdb
switched to db newdb

在 MongoDB 中默認(rèn)數(shù)據(jù)庫是:test

2.刪除數(shù)據(jù)庫

使用db.dropDatabase()命令可以刪除數(shù)據(jù)庫。如果沒有選擇任何數(shù)據(jù)庫,那么它將刪除默認(rèn)的’test‘?dāng)?shù)據(jù)庫

3.查詢數(shù)據(jù)庫列表

>show dbs
local     0.000025GB
test      0.00002GB

4.創(chuàng)建Collection

先通過use DataBaseName命令選中想要創(chuàng)建集合的數(shù)據(jù)庫,使用命令db.createCollection("collectionName")創(chuàng)建collection

>use newdb
switched to db newdb
>db.createCollection("mycollection")
{ "ok" : 1 }
>

4.刪除集合

MongoDB 的 db.collection.drop() 用于從數(shù)據(jù)庫中刪除集合

5.插入文檔

使用insert()命令插入到MongoDB集合中。

db.CollectionName.insert(
{
    "_id":"100",
    "title":"MongoDB",
    "description":"Description of MongoDB",
    "url":"http://www.baidu.com"
}
)

如果不在文檔中指定_id,insert方法會自動為文檔分配id.
一次插入多個文檔,可以在insert()語句中插入多個文檔。文檔用逗號隔開,再使用中括號把所有文檔括起來。

db.CollectionName.insert([
   {
      _id: 101,
       title: 'MongoDB Guide', 
      description: 'MongoDB is no sql database',
      by: 'yiibai tutorials',
      url: 'http://www.yiibai.com',
      tags: ['mongodb', 'database', 'NoSQL'],
      likes: 100
   },

   {
      _id: 102,
      title: 'NoSQL Database', 
      description: "NoSQL database doesn't have tables",
      by: 'yiibai tutorials',
      url: 'http://www.yiibai.com',
      tags: ['mongodb', 'database', 'NoSQL'],
      likes: 210, 
      comments: [
         {
            user:'user1',
            message: 'My first comment',
            dateCreated: new Date(2017,11,10,2,35),
            like: 0 
         }
      ]
   },
   {
      _id: 104,
      title: 'Python Quick Guide', 
      description: "Python Quick start ",
      by: 'yiibai tutorials',
      url: 'http://www.yiibai.com',
      tags: ['Python', 'database', 'NoSQL'],
      likes: 30, 
      comments: [
         {
            user:'user1',
            message: 'My first comment',
            dateCreated: new Date(2018,11,10,2,35),
            like: 590 
         }
      ]
   }
])

6.查詢文檔

使用db.COLLECTION_NAME.find(document)
查詢文檔。find()方法會找出collection中的所有文檔。
帶參find()方法,第一個參數(shù)用來指定查詢條件,第二個參數(shù)用來表示要檢索的字段列表。字段列表對應(yīng)值設(shè)置為1即為顯示,設(shè)置為0即為隱藏字段。

> db.mycol.find({}, {'_id':1, 'title':1})
{ "_id" : 101, "title" : "MongoDB Guide" }
{ "_id" : 102, "title" : "NoSQL Database" }
{ "_id" : 104, "title" : "Python Quick Guide" }
{ "_id" : 100, "title" : "MongoDB Overview" }
>

第一個參數(shù)可以指定查詢過濾器,或類似關(guān)系型數(shù)據(jù)庫指定一些操作符或查詢運(yùn)算符

>db.mycol.find({"likes": {$gt:10}, $or: [{"by": "yiibai tutorials"},
   {"title": "MongoDB Overview"}]}).pretty()  #and 和 or一起使用
   
{
   "_id": 100,
   "title": "MongoDB Overview", 
   "description": "MongoDB is no sql database",
   "by": "yiibai tutorials",
   "url": "http://www.yiibai.com",
   "tags": ["mongodb", "database", "NoSQL"],
   "likes": "100"
}
>

查詢限制數(shù)量
使用db.COLLECTION_NAME.find().limit(NUMBER)指令可以限制查詢NUMBER條
查詢跳過條目
使用skip()函數(shù)跳過一定量的些條目db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

7.更新文檔

update方法更新現(xiàn)有文檔中的值db.COLLECTION_NAME.update(SELECTION_CRITERIA, UPDATED_DATA)

>db.mycol.update({'title':'MongoDB Overview'},
   {$set:{'title':'New Update MongoDB Overview'}},{multi:true})

save()方法傳遞新的文檔數(shù)據(jù)替換現(xiàn)有文檔

8.聚合

在關(guān)系型數(shù)據(jù)庫中使用count(*)和group by組合產(chǎn)生聚合功能,而在MongoDB中應(yīng)該使用aggregate()函數(shù)
假設(shè)我們的集合中有以下數(shù)據(jù)

db.article.insert([
{
   _id: 100,
   title: 'MongoDB Overview',
   description: 'MongoDB is no sql database',
   by_user: 'Maxsu',
   url: 'http://www.yiibai.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: 101,
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'Maxsu',
   url: 'http://www.yiibai.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: 102,
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'Kuber',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},
{
   _id: 103,
   title: 'MySQL Overview', 
   description: 'MySQL is sql database',
   by_user: 'Curry',
   url: 'http://www.yiibai.com/mysql/',
   tags: ['MySQL', 'database', 'SQL'],
   likes: 350
}])

現(xiàn)在從上面的集合中,如果要顯示一個列表,說明每個用戶寫入了多少個教程,那么可使用以下aggregate函數(shù)

> db.article.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{ "_id" : "Curry", "num_tutorial" : 1 }
{ "_id" : "Kuber", "num_tutorial" : 1 }
{ "_id" : "Maxsu", "num_tutorial" : 2 }
>

9.主從復(fù)制

主從復(fù)制是MongoDB最常用的復(fù)制的方式,可用于備份、故障恢復(fù)、讀擴(kuò)展等。
首先需要建立一個主節(jié)點(diǎn)和一個或多個從節(jié)點(diǎn),每個從節(jié)點(diǎn)需要知道主節(jié)點(diǎn)的地址。運(yùn)行mongod -master啟動主節(jié)點(diǎn)。運(yùn)行mongod --slave --source master_address啟動從節(jié)點(diǎn)。

生產(chǎn)環(huán)境下可能會有多臺服務(wù)器,我們在同一臺服務(wù)器上替代實(shí)驗(yàn)。首先需要給主節(jié)點(diǎn)建立數(shù)據(jù)目錄,并綁定端口號(10000):

$ mkdir -p ~/dbs/master
$ ./mongod --dbpath ~/dbs/master --port 10000 --master

接著設(shè)置從節(jié)點(diǎn),需要選擇不同的目錄和端口,并且使用--source為從節(jié)點(diǎn)指明主節(jié)點(diǎn)的地址:

$ mkdir -p ~/dbs/slave
$ ./mongod --dbpath ~/dbs/slave --port 10001 --slave --source localhost:10000

這種方式只能從節(jié)點(diǎn)從主節(jié)點(diǎn)復(fù)制,還沒有能夠從從節(jié)點(diǎn)復(fù)制的機(jī)制,因?yàn)閺墓?jié)點(diǎn)不保存自己的oplog。

10.副本集

副本集是具有自動故障恢復(fù)的主從集群。主從集群沒有固定的主節(jié)點(diǎn),整個集群會推舉出一個主節(jié)點(diǎn),檔主節(jié)點(diǎn)無法工作時,變更到其他的節(jié)點(diǎn)。即,副本集總會有一個活躍節(jié)點(diǎn)(primary)和一個或多個備份節(jié)點(diǎn)(secondary)。
現(xiàn)在我們來將獨(dú)立的MongoDB實(shí)例轉(zhuǎn)換為副本集。
首先我們需要找到機(jī)器的主機(jī)名

$ cat /etc/hostname
morton

接著我們要關(guān)機(jī)現(xiàn)有的MongoDB服務(wù)器,啟動新的服務(wù)器

mongod --port 27017 --dbpath "D:\set up\mongodb\data" --replSet rs0

--replSet的作用是讓服務(wù)器知道,這個rs0服務(wù)器還有其他的同伴還未啟動。
以同樣的方式啟動多臺。
然后在shell中,連接其中一個服務(wù)器(使用morton:10001),初始化副本集:

$ ./mongo morton:10001/admin

11.MongoDB的關(guān)聯(lián)關(guān)系

MongoDB中的關(guān)系指的是各個文檔之間在邏輯上的相互關(guān)聯(lián)。關(guān)系可以使用嵌入式和引用方法兩種方式構(gòu)建。這種關(guān)系可以是1:1,1:N,N:N。
假設(shè)我們需要存儲用戶和用戶的地址。而一個用戶可以有多個地址,這就是一個1:N的關(guān)系。
以下是用戶文檔結(jié)構(gòu):

{
   "_id":10999110,
   "name": "Maxsu",
   "contact": "13888990021",
   "dob": "1992-10-11"
}

以下是地址(address)文檔的結(jié)構(gòu):

{
   "_id":12200,
   "building": "Hainan Building NO.2100",
   "pincode": 571100,
   "city": "Haikou",
   "province": "Hainan"
}

下面分別通過嵌入式和引用式兩種方式來構(gòu)建關(guān)系:

嵌入式

在嵌入式方法中,我們直接將地址文檔(address)嵌入到用戶(user)文檔中去。

{
   "_id": 21000100,
   "contact": "13800138000",
   "dob": "1991-11-11",
   "name": "Maxsu",
   "address": [
      {
         "building": "Hainan Building NO.2100",
         "pincode": 571100,
         "city": "Haikou",
         "province": "Hainan"
      },
      {
         "building": "Sanya Building NO.2100",
         "pincode": 572200,
         "city": "Sanya",
         "province": "Hainan"
      },
   ]
}

這種方式將數(shù)據(jù)保存在同一個文檔中,數(shù)據(jù)的檢索和維護(hù)比較容易。

> db.users.findOne({"name":"Maxsu"},{"address":1, "name":1})

但是如果嵌入式文檔不斷增大,就會影響到讀寫的性能。

引用

這是設(shè)計(jì)規(guī)范化關(guān)系的方法。 在這種方法中,用戶和地址文件將分別維護(hù),但用戶文檔將包含一個將引用地址文檔的id字段的字段。
我們可以將addresswen文檔存在其它的集合中,將其引用添加到用戶文檔即可。我們使用使用DBRefs來引用文檔。它適用于文檔引用多個集合中的文檔的情況。

{
   "_id": 21000100,
   "contact": "13800138000",
   "dob": "1991-11-11",
   "name": "Maxsu",
   "address": [
      {
        "$ref":"address_home",
        "$id":ObjectId("12200"),
        "$db":"myDB"   
      },
      {
         "$ref":"address_home",
        "$id":ObjectId("12201"),
        "$db":"myDB"   
      },
   ]
}

DBRefs中有三個字段 -

  • $ref - 此字段指定引用文檔的集合
  • $id - 此字段指定引用文檔的_id字段
  • $db - 這是一個可選字段,并包含引用文檔所在的數(shù)據(jù)庫的名稱
    接下來我們就可以通過引用查到用戶的地址。
>var user = db.users.findOne({"name":"Maxsu"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id":(dbRef.$id)})

12.Map Reduce

Map-reduce是將大量數(shù)據(jù)合并為有用的聚合結(jié)果的數(shù)據(jù)處理范例。MapReduce通常用于處理大型數(shù)據(jù)集。MongoDB使用MapReduce可以構(gòu)建出大型復(fù)雜聚合查詢。
以下是基本 mapReduce 命令的語法 -

>db.collection.mapReduce(
   function() {emit(key,value);},  //map function
   function(key,values) {return reduceFunction}, {   //reduce function
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)

map-reduce函數(shù)首先查詢集合,然后將結(jié)果文檔映射到發(fā)出的鍵值對,然后根據(jù)具有多個值的鍵進(jìn)行減少。

在上面的語法 -

map是一個JavaScript函數(shù),它將一個值與一個鍵映射并發(fā)出一個鍵值對;
reduce是一個javascript功能,可以減少或分組具有相同鍵的所有文檔;
out指定map-reduce查詢結(jié)果的位置;
query指定選擇文檔的可選選擇條件;
sort指定可選的排序條件;
limit指定可選的最大文檔數(shù);
接下來我們來使用MapReduce
考慮存儲用戶帖子的以下文檔結(jié)構(gòu)。 該文檔存儲用戶的user_name和帖子的狀態(tài)(status)。

{
   "post_text": "abcd",
   "user_name": "maxsu",
   "status":"active"
}

現(xiàn)在我們需要選出所有status為active的帖子,并根據(jù)user_name進(jìn)行分組

>db.posts.mapReduce( 
   function() { emit(this.user_id,1); }, 
   function(key, values) {return Array.sum(values)}, {  
      query:{status:"active"},  
      out:"post_total" 
   }
)

返回結(jié)果

{
   "result" : "post_total",
   "timeMillis" : 9,
   "counts" : {
      "input" : 4,
      "emit" : 4,
      "reduce" : 2,
      "output" : 2
   },
   "ok" : 1,
}

結(jié)果表明:共有4個文檔與查詢匹配,mapper函數(shù)發(fā)出4哥鍵值對文檔,最終將具有相同鍵的reduce函數(shù)分組的映射文檔分解為2。在MapReduce函數(shù)后直接加find()函數(shù)就可以將我們想要的條目查詢出來。查詢結(jié)果如下:

{ "_id" : "tom", "value" : 2 }
{ "_id" : "maxsu", "value" : 2 }

13.文本搜索

從MongoDB 2.4開始,默認(rèn)文本搜索功能是自動啟用狀態(tài)。
假設(shè)我們需要查詢一些博客。我們先新建blogs集合。然后在blogs集合中插入一些文檔。

db.blogs.insert({_id:1,title:"search",content:"MongoDB search"})
 
db.blogs.insert({_id:2,title:"Map Reduce",content:"Map-reduce"})
 


只有擁有Text index的collection才可以全文檢索,因此我們需要構(gòu)建Text index。一個collection只能有一個Text index,但是一個Text index可以有多個字段。

db.blogs.ensureIndex({title:"text",content:"text"})

接下來我們就可以通過索引去搜索。

簡單的全文搜索
db.blogs.find({$text:{$search:"MongoDB"}})

返回值

{_id:1,title:"search",content:"MongoDB search"}
查詢包含MongoDB不包含Map的記錄
db.blogs.find({$text:{$search:"MongoDB -Map"}})

返回值

{_id:1,title:"search",content:"MongoDB search"}
查詢含有MongoDB search的條目
db.blogs.find({$text:{$search:"\"MongoDB search\""}})
使用權(quán)重排序搜索結(jié)果

默認(rèn)情況下,全文搜索是無順序的,但是我們可以使用$meta textScore來獲得每個文檔對這個搜索的匹配程度,并使用其進(jìn)行排序


1
db.blogs.find( {$text:{$search:"MongoDB"}}, {score:{$meta:"textScore"}} ).sort({score:{$meta:"textScore"}})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容