1. 程式人生 > >MongoDB上手之操作篇

MongoDB上手之操作篇

什麼是MongoDB

  • MongoDB是一個基於分散式檔案儲存的開源資料庫系統
  • MongoDB 將資料儲存為一個文件,資料結構由鍵值(key=>value)對組成。MongoDB 文件類似於 JSON 物件。欄位值可以包含其他文件,陣列及文件陣列。

MongoDB安裝

windows安裝

Windows官方安裝指南

mac安裝

Mac官方安裝指南

  1. 先安裝homebrew

    http://brew.sh/
    
  2. 使用brew安裝mongodb

    brew install mongodb
    
  3. 再安裝視覺化工具 Robomongo

3. mongodb啟動與連線

3.1 windows啟動伺服器端

  1. 找到mongodb安裝目錄,一般是 C:\Program Files\MongoDB 2.6 Standard\bin

  2. 按下Shift+滑鼠右鍵,選擇在此處開啟命令視窗 img

  3. 在除C盤外的碟符新建一個空目錄,如 D:\Mongodb\data

  4. 在命令列中輸入

    mongod --dbpath=剛建立的空目錄
    

    ,如

    mongod --dbpath=D:\Mongodb\data
    
  5. 再按回車鍵 img

  6. 如果出現waiting for connections on port 27017就表示啟動成功,已經在27017埠上監聽了客戶端的請求

  7. 注意:--dbpath後的值表示資料庫檔案的儲存路徑,而且後面的路徑必須事先建立好,必須已經存在,否則服務開啟失敗

  8. 注意:這個命令窗體絕對不能關

    ,關閉這個視窗就相當於停止了mongodb服務

3.2 啟動客戶端連線伺服器

  1. 找到mongodb安裝目錄,一般是 C:\Program Files\MongoDB 2.6 Standard\bin

  2. 按下Shift+滑鼠右鍵,選擇在此處開啟命令視窗 img

  3. 命令窗體中輸入 mongo --host=127.0.0.1 或者 mongo 按回車鍵

    備註:–host後的值表示伺服器的ip地址 備註: --host=127.0.0.1 表示的就是本地伺服器,每次資料庫都會預設連線test資料庫


img

配置Mongodb服務

  • 刪除服務
sc delete mongodb
  • 新增服務
mongod.exe --dbpath E:\mdata --logpath E:\mlog --logappend --directoryperdb --serviceName mongodb --install

net start mongodb
net stop mongodb

MongoDB基本概念

  • 資料庫 MongoDB的單個例項可以容納多個獨立的資料庫,比如一個學生管理系統就可以對應一個數據庫例項
  • 集合 資料庫是由集合組成的,一個集合用來表示一個實體,如學生集合
  • 文件 集合是由文件組成的,一個文件表示一條記錄,比如一位同學張三就是一個文件

img img

資料庫操作

  • 使用資料庫

語法

use database_name      database_name代表資料庫的名字

注:如果此資料庫存在,則切換到此資料庫下,如果此資料庫還不存在也可以切過來

例項 切換到 school資料庫下

檢視所有資料庫

語法

show dbs

備註: 我們剛建立的資料庫school如果不在列表內, 要顯示它,我們需要向school資料庫插入一些資料

db.students.insert({name:'hello', age:1});

檢視當前使用的資料庫

語法

db 或 db.getName()

注:db代表的是當前資料庫 也就是school這個資料庫

刪除資料庫

語法

db.dropDatabase()

集合操作

  • 檢視集合幫助

語法

db.students.help()
  • 檢視資料庫下的集合

語法

show collections
  • 建立集合

建立一個空集合

db.createCollection(collection_Name)
  • collection_Name集合的名稱

建立集合並插入一個文件

  • collection_Name集合的名稱
  • document要插入的文件
 db.collection_Name.insert(document)

插入文件

  • insert

語法

 db.collection_name.insert(document)

引數

  • collection_name 集合的名字
  • document 插入的文件

每當插入一條新文件的時候mongodb會自動為此文件生成一個_id屬性,_id一定是唯一的,用來唯一標識一個文件 _id也可以直接指定,但如果資料庫中此集合下已經有此_id的話插入會失敗

> db.students.insert({_id:1,name:'zfpx',age:1});
WriteResult({ "nInserted" : 1 })
> db.students.insert({_id:1,name:'zfpx',age:1});

save

save方法有更新和插入兩種功能,到底是插入還是更新文件取決於save的引數

語法

db.collection_name.save(document)

引數

  • collection_name 集合的名字
  • document 插入的文件

注:如果不指定sb新該 _id 的資料。

  1. insert: 若新增資料的主鍵已經存在,則會拋 org.springframework.dao.DuplicateKeyException 異常提示主鍵重複,不儲存當前資料。
  2. save: 若新增資料的主鍵已經存在,則會對當前已經存在的資料進行修改操作。

例項

> db.students.save({_id:1,name:'hello',age:1});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
> db.students.save({_id:1,name:'hello',age:100});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

更新文件

MongoDB 使用 update()save() 方法來更新集合中的文件

語法

db.collection.update(
   <query>,
   <updateObj>,
   {
     upsert: <boolean>,
     multi: <boolean>
   }
)

引數說明

  • query 查詢條件,指定要更新符合哪些條件的文件
  • update 更新後的物件或指定一些更新的操作符
    • $set直接指定更新後的值
    • $inc在原基礎上累加
  • upsert 可選,這個引數的意思是,如果不存在符合條件的記錄時是否插入updateObj. 預設是false,不插入。
  • multi 可選,mongodb 預設只更新找到的第一條記錄,如果這個引數為true,就更新所有符合條件的記錄。

例項students集合中資料中name是zfpx2的值修改為zfpx22

> db.students.update({name:'zfpx2'},{age:300});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

注:如果有多條name是zfpx2的資料只更新一條,如果想全部更新需要指定{multi:true}的引數

db.students.update({name:'zfpx2'},{$set:{age:300}},{multi:true});
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 1 })

$set

直接指定更新後的值

$inc

在原基礎上累加

$unset

刪除指定的鍵

upsert

插入或更新

multi

批量插入

$push

向陣列中新增元素

var result = db.student.update({name:'張三'},{
    $push:{"hobbys":"smoking"}
});

$ne

$ne selects the documents where the value of the field is not equal to the specified value. This includes documents that do not contain the field.

就是排除指定欄位的文件

db.student.update({name:'張三',friends:{$ne:'Nami'}},{
    $push:{"friends":"Nami"}
});

$addToSet

新增值到一個數組中去,如果陣列中已經存在該值那麼將不會有任何的操作

db.student.update({name:'張三'},{$addToSet:{friends:"Wusopu"}});

{ $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } }

$each

let newFriends = ["A",'B'];
var result = db.student.update({name:'張三'},{$addToSet:{friends:{$each:newFriends}}});

{ $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }

$pop

db.student.update({name:'張三'},{$pop:{
    friends:1
}});

修改指定索引元素

 db.student.update({name:'張三'},{$set:{
    "friends.1":"Nami2"
}});

runCommand

可以配置執行指定的資料庫命令,通過配置。可以生成MySQL或者MongoDB的操作語句

 var modify = {
    findAndModify:'student',
    query:{name:'張三'},
    update:{$set:{age:100}},
    fields:{name:'1'},
    sort:true,
    new:true //返回修改後的值
}

var result = db.runCommand(modify);
printjson(result);

文件的刪除

remove方法是用來移除集合中的資料

語法

db.collection.remove(
   <query>,
   {
     justOne: <boolean>
   }
)

引數說明

  • query :(可選)刪除的文件的條件。
  • justOne : (可選)如果設為 true 或 1,則只刪除匹配到的多個文件中的第一個

例項 刪除worker集合裡name是zfpx2的所有文件資料

> db.students.remove({name:'zfpx2'});
WriteResult({ "nRemoved" : 2 })

即使匹配多條也只刪除一條

> db.students.remove({name:"zfpx2"},{justOne:true})
WriteResult({ "nRemoved" : 1 })

查詢文件

  • find

語法

db.collection_name.find()

引數

  • collection_name 集合的名字

例項 查詢students下所有的文件

db.students.find()
  • 查詢指定列

語法

db.collection_name.find({queryWhere},{key:1,key:1})

引數列表

  • collection_name 集合的名字
  • queryWhere 參閱查詢條件操作符
  • key 指定要返回的列
  • 1 表示要顯示

例項 只返回顯示age列

> db.students.find({},{age:1});
  • findOne

查詢匹配結果的第一條資料 語法

db.collection_name.findOne()

例項

db.students.findOne()
  • $in

    age等於20, 或者100的文件

db.student.find({age:{$in:[30,100]}},{name:1,age:1});
  • $nin

    查詢age在30 - 100 之間的資料

db.student.find({age:{$nin:[30,100]}},{name:1,age:1});
  • $not

    搜尋age大於20 並且小於30的值

db.student.find({age:{$not:{$gte:20,$lte:30}}});
  • array
//按所有元素匹配
//let result = db.student.find({friends:[ "Lufy", "Nami2", "Wusopu", "A" ]});
//匹配一條
//let result = db.student.find({friends:"A"});
//$all
//let result = db.student.find({friends:{$all:['A',"Lufy"]}});
//$in
//let result = db.student.find({friends:{$in:['A',"Lufy"]}});
//$size
//let result = db.student.find({friends:{$size:4}});
//$slice
//let result = db.student.find({friends:{$size:5}},{name:1,friends:{$slice:1}});
//let result = db.student.find({friends:{$size:5}},{name:1,friends:{$slice:-1}});

where

db.student.find({$where:"this.age>30"},{name:1,age:1});

cursor

遊標,反正我不懂,就不寫了,以後懂了再說

var result = db.student.find();

//while(result.hasNext()){
//    printjson(result.next());
//}

result.forEach(element=>printjson(element));

條件操作符

條件操作符用於比較兩個表示式並從mongoDB集合中獲取資料

  • 大於操作符

語法

db.collectoin_name.find({<key>:{$gt:<value>}})

引數

  • collectoin_name 集合名稱
  • key 欄位
  • value 值

查詢age 大於 30的資料

db.students.find({age:{$gt:30}})
  • 大於等於操作符

語法

db.collectoin_name.find({<key>:{$gte:<value>}})

引數

  • collectoin_name 集合名稱
  • key 欄位
  • value 值

查詢age 3大於等於30 的資料

db.students.find({age: {$gte: 30}})
  • 小於操作符

語法

db.collectoin_name.find( {<key>:{$lt:<value>}})

引數

  • collectoin_name集合名稱
  • key 欄位
  • value 值

例項

db.students.find({age: {$lt: 30}}) 查詢age 小於30的資料
  • 小於等於操作符

語法

db.collectoin_name.find({<key>:{$lte:<value>}})

引數

  • collectoin_name集合名詞
  • key欄位
  • value值

查詢age 小於等於30的資料

db.students.find({age: {$lte: 30}})
  • 同時使用 $gte$lte

語法

db.collectoin_name.find({<key>:{$gte:<value>},<key>:{$lte:<value>}})

引數

  • collectoin_name 集合名稱
  • key 欄位
  • value 值

例項 查詢age 大於等於 30 並且 age 小於等於 50 的資料

db.students.find({age: {$gte: 30, $lte: 50}})
  • 等於

語法

db.collectoin_name.find({<key>:<value>,<key>:<value>})

引數

  • collectoin_name集合名詞
  • key欄位
  • value值

查詢age = 30的資料

db.students.find({"age": 30})`
  • 使用 _id進行查詢

語法

db.collectoin_name.find({"_id" : ObjectId("value")})

引數

  • value _id的值

例項 查詢_id是 562af23062d5a57609133974 資料

> db.students.find({_id:ObjectId("5adb666ecd738e9771638985")});
{ "_id" : ObjectId("5adb666ecd738e9771638985"), "name" : "zzzz" }
  • 查詢結果集的條數

語法

db.collectoin_name.find().count()

引數

  • collectoin_name 集合名稱

例項

db.students.find().count()
  • 正則匹配

語法

db.collection.find({key:/value/})

引數

  • collectoin_name 集合名稱
  • key 欄位
  • value 值

例項 查詢name裡包含zhang的資料

db.students.find({name:/value/})

查詢某個欄位的值當中是否以另一個值開頭

db.students.find({name:/^zhang/})

與和或

  • and

find方法可以傳入多個鍵(key),每個鍵(key)以逗號隔開

語法

db.collection_name.find({key1:value1, key2:value2})

例項 查詢name是leo並且age是1的資料

db.students.find({name:'leo',age:1})
  • or

語法

db.collection_name.find(
   {
      $or: [
   {key1: value1}, {key2:value2}
      ]
   }
)

例項 查詢age = 30 或者 age = 50 的資料

db.students.find({$or:[{age:30},{age:50}]})
  • and和or聯用

語法

db.collection_name.find(
   {
     key1:value1,
     key2:value2,
     $or: [
   {key1: value1},
   {key2:value2}
     ]
   }
)

例項 查詢 name是leo並且 age是30 或者 age是 50 的資料

db.students.find({name:'leo',$or:[{age:30},{age:50}]})

分頁查詢

  • limit

讀取指定數量的資料記錄 語法

db.collectoin_name.find().limit(number)

引數

  • collectoin_name集合
  • number讀取的條數

例項 查詢前3條資料

db.students.find().limit(3)
  • skip

跳過指定數量的資料,skip方法同樣接受一個數字引數作為跳過的記錄條數 語法

db.collectoin_name.find().skip(number)

引數

  • collectoin_name集合
  • number跳過的條數

例項 查詢3條以後的資料

db.students.find().skip(3)
  • skip+limit

通常用這種方式來實現分頁功能 語法

db.collectoin_name.find().skip(skipNum).limit(limitNum)

引數

  • collectoin_name 集合名稱
  • skipNum 跳過的條數
  • limitNum 限制返回的條數

例項 查詢在4-6之間的資料

db.students.find().skip(3).limit(3);
  • sort排序

sort()方法可以通過引數指定排序的欄位,並使用 1 和 -1 來指定排序的方式,其中 1 為升序排列,而-1是用於降序排列。 語法

db.collectoin_name.find().sort({key:1})
db.collectoin_name.find().sort({key:-1})

引數

  • collectoin_name集合
  • key表示欄位

例項 查詢出並升序排序 {age:1} age表示按那個欄位排序 1表示升序

db.students.find().sort({age:1})
  • 執行指令碼

    有時候我們寫命令列不方便,可以把操作寫成一個指令碼,然後執行

語法

mongo insert.js
var username = 'leo';
var password = '123456';
var user = { "username": username, "password": password };
var db = connect('students');//選擇users資料庫
var result = db.users.insert(user);
print('write ' + result);
var start = Date.now();
var db = connect('students');
for (var i = 0; i < 1000; i++) {
    db.users.insert({ "username": "zfpx" + i });
}
var cost = Date.now() - start;
print('cost ' + cost + ' ms');
var start = Date.now();
var db = connect('students');
var users = [];
for (var i = 0; i < 1000; i++) {
    users.push({ "username": "zfpx" + i });
}
db.users.insert(users);
var cost = Date.now() - start;
print('cost ' + cost + ' ms');

索引

建立索引是會消耗效能的,只有在在按照某個欄位查詢的時候才給該欄位建一個索引,方便查詢,有助於提升效能

db.users.getIndexes();
db.users.ensureIndex({name:1});
db.users.find({someother:'28903',name:'huqo3vx'}).hint({someother:1});

db.articles.ensureIndex({content:'text'});
db.articles.find({$text:{$search:"1"}});
db.articles.find({$text:{$search:"1 2 3 -4"}});
db.articles.find({$text:{$search:"1 2 3 -4"}});
db.articles.find({$text:{$search:"\"2 3\""}});

備份與匯出

想要匯出真個資料庫的時候,集合的欄位不用設定

// 匯出資料
mongodump
    -- host 127.0.0.1
    -- port 27017
    -- out D:/databack/backup
    -- collection mycollection
    -- db test
    -- username
    -- password
//mongodump --host 127.0.0.1 --port 27017 --out ./backup --collection users --db school
//db.users.drop();

// 恢復資料
mongorestore
--host
--port
--username
--password
mongorestore --host 127.0.0.1 --port 27017 D://backup/

許可權

// 1.建立使用者
db.createUser({
    user:'root',
    pwd:'123456',
    customData:{ // 額外資訊,可以不設定
        name:'root',
        email:'[email protected]',
        age:18
    },
    roles:[ // 使用者角色許可權 必須設定
        {
          role:'readWrite', // 讀寫許可權
          db:'school' // 可以操作的資料庫
        },
        'read'
    ]
});
// 2.
db.system.users.remove({user:'root'});
// 3. 帶許可權啟動資料庫
mongod --auth
// 4. 登入帶許可權的資料庫
mongo -u root -p 123456 127.0.0.1:27017

附錄

ObjectId構成

之前我們使用MySQL等關係型資料庫時,主鍵都是設定成自增的。但在分散式環境下,這種方法就不可行了,會產生衝突。為此,MongoDB採用了一個稱之為ObjectId的型別來做主鍵。ObjectId是一個12位元組的 BSON 型別字串。按照位元組順序,一次代表:

  • 4位元組:UNIX時間戳
  • 3位元組:表示執行MongoDB的機器
  • 2位元組:表示生成此_id的程序
  • 3位元組:由一個隨機數開始的計數器生成的值

附錄

Mongodb啟動命令mongod引數說明

選項 含義
–port 指定服務埠號,預設埠27017
–logpath 指定MongoDB日誌檔案,注意是指定檔案不是目錄
–logappend 使用追加的方式寫日誌
–dbpath 指定資料庫路徑
–directoryperdb 設定每個資料庫將被儲存在一個單獨的目錄

集合命令

  • db.students.help();

  • DBCollection help

  • db.students.find().help() - show DBCursor help 顯示遊標幫助

  • db.students.count() 顯示條數

  • db.students.copyTo(newColl) - duplicates collection by copying all docum ents to newColl; no indexes are copied. 把一箇舊集合拷貝到一個新的集合,不拷貝索引

  • db.students.convertToCapped(maxBytes) - calls {convertToCapped:'students ', size:maxBytes}} command

  • db.students.dataSize() 資料大小

  • db.students.distinct( key ) - e.g. db.students.distinct( ‘x’ ) 統計唯一的key的數量

  • db.students.drop() drop the collection ,刪除集合

  • db.students.dropIndex(index) - e.g. db.students.dropIndex( “indexName” ) 刪除索引 or db.students.dropIndex( { “indexKey” : 1 } )

  • db.students.dropIndexes() 刪除 所有的索引

  • db.students.ensureIndex(keypattern[,options]) - options is an object wit h these possible fields: name, unique, dropDups 新增索引

  • db.students.reIndex()

  • db.students.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to return. 查詢文件

         e.g. db.students.find( {x: 77} , {name:1, x:1} )
    
  • db.students.find(…).count() 數量

  • db.students.find(…).limit(n) 限制返回的條數

  • db.students.find(…).skip(n) 設定跳過的條數

  • db.students.find(…).sort(…) 排序

  • db.students.findOne([query]) 查詢一條

  • db.students.findAndModify( { update : … , remove : bool [, query: {}, sort: {}, ‘new’: false] } ) 查詢並且修改 更新後的值,是否刪除,查詢條件 排序 是否返回新值

  • db.students.getDB() get DB object associated with collection 獲得DB

  • db.students.getPlanCache() get query plan cache associated with collecti on

  • db.students.getIndexes() 獲取索引

  • db.students.group( { key : …, initial: …, reduce : …[, cond: …] } ) 分組統計

  • db.students.insert(obj) 插入文件

  • db.students.mapReduce( mapFunction , reduceFunction , ) 統計

  • db.students.aggregate( [pipeline], ) - performs an agg regation on a collection; returns a cursor 聚合

  • db.students.remove(query) 刪除

  • db.students.renameCollection( newName , ) renames the colle ction. 重新命名集合

  • db.students.runCommand( name , ) runs a d