MongoDB上手之操作篇
什麼是MongoDB
- MongoDB是一個基於分散式檔案儲存的開源資料庫系統
- MongoDB 將資料儲存為一個文件,資料結構由鍵值(key=>value)對組成。MongoDB 文件類似於 JSON 物件。欄位值可以包含其他文件,陣列及文件陣列。
MongoDB安裝
windows安裝
- mongodb32位安裝版 連結: https://pan.baidu.com/s/1SHJ1vre_CQOE3u-W0zniqQ 密碼: chan
- MongoDB64位綠色版 連結: https://pan.baidu.com/s/1EkAB2SrcU1mfMfff_WDxtA
- mongo客戶端 連結: https://pan.baidu.com/s/1YFxLZ-55D-WFR8os2fXN0A 密碼: 61qd
mac安裝
-
先安裝homebrew
http://brew.sh/
-
使用brew安裝mongodb
brew install mongodb
-
再安裝視覺化工具 Robomongo
3. mongodb啟動與連線
3.1 windows啟動伺服器端
-
找到mongodb安裝目錄,一般是
C:\Program Files\MongoDB 2.6 Standard\bin
-
按下Shift+滑鼠右鍵,選擇在此處開啟命令視窗
-
在除C盤外的碟符新建一個空目錄,如
D:\Mongodb\data
-
在命令列中輸入
mongod --dbpath=剛建立的空目錄
,如
mongod --dbpath=D:\Mongodb\data
-
再按回車鍵
-
如果出現
waiting for connections on port 27017
就表示啟動成功,已經在27017埠上監聽了客戶端的請求 -
注意:
--dbpath
後的值表示資料庫檔案的儲存路徑,而且後面的路徑必須事先建立好,必須已經存在,否則服務開啟失敗 -
注意:這個命令窗體絕對不能關
mongodb
服務
3.2 啟動客戶端連線伺服器
-
找到mongodb安裝目錄,一般是
C:\Program Files\MongoDB 2.6 Standard\bin
-
按下Shift+滑鼠右鍵,選擇在此處開啟命令視窗
-
命令窗體中輸入 mongo --host=127.0.0.1 或者 mongo 按回車鍵
備註:–host後的值表示伺服器的ip地址 備註: --host=127.0.0.1 表示的就是本地伺服器,每次資料庫都會預設連線test資料庫
配置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的單個例項可以容納多個獨立的資料庫,比如一個學生管理系統就可以對應一個數據庫例項
- 集合 資料庫是由集合組成的,一個集合用來表示一個實體,如學生集合
- 文件 集合是由文件組成的,一個文件表示一條記錄,比如一位同學張三就是一個文件
資料庫操作
- 使用資料庫
語法
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 的資料。
- insert: 若新增資料的主鍵已經存在,則會拋 org.springframework.dao.DuplicateKeyException 異常提示主鍵重複,不儲存當前資料。
- 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 thefield
is not equal to the specifiedvalue
. This includes documents that do not contain thefield
.就是排除指定欄位的文件
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