MongoDB安裝和入門
什麼是MongoDB
MongoDB是一個文件資料庫,提供好的效能,領先的非關係型資料庫。採用BSON儲存文件資料。2007年10月,MongoDB由10gen團隊所發展。2009年2月首度推出。MongoDB用c++編寫的。
優勢:
-
面向文件的儲存:以 JSON 格式的文件儲存資料。
-
任何屬性都可以建立索引。
-
複製以及高可擴充套件性。
-
自動分片。
-
豐富的查詢功能。
-
快速的即時更新。
-
來自 MongoDB 的專業支援。
mongodb安裝與啟動
mongodb下載網址: https://www.mongodb.com/download-center/community
選擇版本、系統環境、包 。以下將以tgz包 為例
下載完成將得到mongodb-linux-x86_64-rhel70-4.2.8.tgz包,將其上傳到linux(centos7)某個目錄
上傳完成後解壓
tar zxvf mongodb-linux-x86_64-rhel70-4.2.8.tgz
移動到/usr/local/mongodb目錄(非必須)
mv mongodb-linux-x86_64-rhel70-4.2.8/ /usr/local/mongodb
建立專門的負責的使用者並賦予許可權(非必須)
cd /usr/local/mongodb groupadd mongodb useradd -s /sbin/nologin -g mongodb -M mongodb mkdir data log run chown -R mongodb:mongodb data log run
在/usr/local/mongodb 裡面建立一個配置檔案 mongodb.conf
vim mongodb.conf 並寫入下面的資訊:
bind_ip=0.0.0.0 port=27017 dbpath=/usr/local/mongodb/data/ logpath=/usr/local/mongodb/log/mongodb.log pidfilepath =/usr/local/mongodb/run/mongodb.pid logappend=true fork=true maxConns=500 noauth = true # 配置解釋: # fork=true 執行在後臺 # logappend=true 如果為 true,當 mongod/mongos 重啟後,將在現有日誌的尾部繼續新增日誌。否則,將會備份當前日誌檔案,然後建立一個新的日誌檔案;預設為 false。 # noauth = true 不需要驗證使用者密碼 # maxConns=500 最大同時連線數 預設2000
以上是MongoDB的安裝與啟動的準備工作,可直接啟動 啟動命令:
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
配置環境變數
vim /etc/profile
在/etc/profile檔案末尾新增一行:
export PATH=/usr/local/mongodb/bin:$PATH
讓其生效:
source /etc/profile
檢視當前mongodb的版本:
mongod --version
MongoDB的crud
理解幾個概念
集合:對應mysql的table
文件:對應mysql的一條資料
資料庫的操作
連線MongoDB,執行mongo命令
mongo
檢視MongoDB自帶的原始資料庫
show dbs
admin:從許可權角度來看,這是“root”資料庫。如果將一個使用者新增到這個資料庫。這個使用者自動繼承所有資料庫的許可權。一些特定的伺服器端命令也只能從這個資料庫執行,比如列出所有的資料庫或者關閉伺服器
local:這個資料永遠不會被複制,可以用來儲存限於本地單臺伺服器的任意集合
config:當mongo用於分片設定時,config資料庫在內部使用。用於儲存分片的相關資訊
建立或進入資料庫:use 資料庫名
use test
使用use時,如果資料庫存在則會進入到相應的資料庫,如果不存在則會自動建立 一旦進入資料庫,則可以使用db來引用當前庫 ;
如果是第一次建立,那個這個資料庫只是存在於記憶體當中,直到這個資料庫中建立了集合後才會持久化到磁碟上
刪除資料庫:db.dropDatabase()
db.dropDatabase()
集合的操作
用於刪除已經持久化的資料庫,剛建立在記憶體中的資料庫刪除無效
相當於恢復到剛建立test資料庫且並沒有持久化到磁碟的狀態
建立一個集合:db.createCollection("集合名稱")
db.createCollection("西遊記")
檢視所有的集合show tables 或者 show collections
show tables
show collections
刪除集合:db.集合名稱.drop()
db.西遊記.drop()
文件的操作
新增一條資料
db.xyj.insert({name:"豬八戒",age:28,gender:"男"})
這裡會自動建立xyj這個集合
查詢資料
db.xyj.find()
可以看到,我們沒有指定id,MongoDB自動給我們生成了一條id,我們也可以指定id,如下
新增一條指定id的資料
db.xyj.insertOne({_id:"workd",name:"豬八戒",age:28,gender:"男"})
當我們向集合中插入文件時,如果沒有給文件指定 _id屬性,則資料庫會自動為文件新增 _id該屬性用來作為文件的唯一標識 _id
我們可以自己指定,如果我們指定了資料庫就不會在添加了,如果自己指定 _id 也必須確保它的唯一性
批量新增資料
db.xyj.insert([ ... {name:"沙和尚",age:38,gender:"男"}, ... {name:"白骨精",age:16,gender:"女"}, ... {name:"蜘蛛精",age:14,gender:"女"} ... ])
或者以下命令也是一樣的效果
db.xyj.insertMany([ {name:"沙和尚",age:38,gender:"男"}, {name:"白骨精",age:16,gender:"女"}, {name:"蜘蛛精",age:14,gender:"女"} ])
總結:
db.collection.insertOne() 插入一個文件物件
db.collection.insertMany() 插入多個文件物件
額外小知識
try{ db.xyj.insert([ {name:"沙和尚",age:38,gender:"男"}, {name:"白骨精",age:16,gender:"女"}, {name:"蜘蛛精",age:14,gender:"女"} ]); }catch(e){ print(e) }
可以知道那條插入失敗
全量修改操作
db.xyj.update({_id: ObjectId("5f0189a368c6a000f725c87b")},{age:NumberInt(30)})
執行效果:這條資料只有age一個欄位了
區域性修改操作
db.xyj.update({_id:ObjectId("5f0189a368c6a000f725c87c")},{$set:{age:NumberInt(30)}})
執行效果:只會修改這條資料的某個欄位
批量修改
db.xyj.update({name:"蜘蛛精"},{$set:{age:NumberInt(100)}},{multi:true})
注意:在修改條資料時,必須要加上第三個引數{multi:true},否則只會修改一條資料
欄位增加操作
db.xyj.update({_id:"workd"},{$inc:{age:NumberInt(1)}})
注意:$inc
對應的欄位必須是數字,而且遞增或遞減的值也必須是數字。
刪除文件
db.xyj.remove({_id:"workd"})
刪除文件欄位
db.xyj.update({"_id": ObjectId("5f0189a368c6a000f725c87d")}, {"$unset": {"name":1}})
$unset
指定欄位的值只需是任意合法值即可
刪除所有
db.xyj.remove({})
陣列操作
插入測試資料
db.xyj.insertMany([ {name:"沙和尚",age:38,gender:"男",hobby:["打籃球","吃喝"]}, {name:"白骨精",age:16,gender:"女",hobby:["吃喝"]}, {name:"蜘蛛精",age:14,gender:"女",hobby:["跑步","打乒乓球"]}, {name:"唐生",age:25,gender:"男",hobby:["坐禪","吃喝"]} ]);
新增陣列內容($push)
db.xyj.update({"name": "白骨精"}, {"$push": {"hobby": "唸佛"}})
刪除元素($pop
)
刪除最後一個元素
db.xyj.update({"_id": ObjectId("5f019375caf12a975c177d10")}, {"$pop": {"hobby": 1}})
刪除第一個元素
db.xyj.update({"_id": ObjectId("5f019375caf12a975c177d13")}, {"$pop": {"hobby": -1}})
刪除特定元素($pull
)
db.xyj.update({"_id": ObjectId("5f019375caf12a975c177d11")}, {"$pull": {"hobby": "唸佛" }})
新增一條測試資料
db.xyj.insert({name:"豬八戒",age:28,gender:"男",address: [{place: "nanji", tel: 123}, {place: "dongbei", tel: 321}]});
更新巢狀陣列的值($set)
db.xyj.update({"_id": ObjectId("5f019881caf12a975c177d14")}, {"$set": {"address.0.tel": 213}})
陣列查詢:
db.xyj.find({"hobby":"跑步"})
多個元素的查詢
db.xyj.find({"hobby":{"$all": ["跑步", "打乒乓球"]}})
只有hobby陣列同時存在跑步和打乒乓球才會匹配
限制陣列長度查詢
db.xyj.find({"hobby": {"$size": 1}})
只有陣列的長度是1才會匹配
投影查詢
db.xyj.find({name:"白骨精"},{name:1,_id:0})
1表示顯示 0表示強制隱藏
相當於sql裡面只查某些欄位
按欄位條件查詢
db.xyj.find({name:"白骨精"})
按欄位條件查詢並只返回一條
db.xyj.findOne({gender:"女"})
其他api就不都演示了
組合查詢:
語法:db.xyj.find($and:[{},{},{}]) //查詢年級大於20小於50的 db.xyj.find({$and:[{age:{$gt:NumberInt(20)}},{age:{$lt:NumberInt(50)}}]}) //查詢名字裡有”精“的或者年紀大於30的 db.xyj.find({$or:[{age:{$gt:NumberInt(30)}},{name:/精/}]})
比較查詢:
db.xyj.find({age:{$gt:NumberInt(20)}}) //查詢年級大於20歲的 $gt--》大於 $lt--》小於 $gte--》大於等於 $lte--》小於等於 $ne---》不等於(不等於不一定要用於數字)
包含查詢:
db.xyj.find({age:{$in:[28,38]}})
不包含:
db.xyj.find({age:{$nin:[28,38]}})
Like:
db.xyj.find({"name": /精/})
統計查詢:
db.xyj.count()或者db.xyj.count({欄位:條件})
取模:
db.xyj.find({"age": {$mod: [5, 1]}}) 比如我們要匹配 age % 5 == 1
是否存在($exists)
db.xyj.find({"love": {"$exists": true}}) // 如果存在欄位love,就返回 db.xyj.find({"love": {"$exists": false}}) // 如果不存在欄位love,就返回
分頁查詢
limit:顯示幾條記錄
skip:跳過幾條記錄
第一次查詢:db.xyj.find().limit(2)
第一次查詢:db.xyj.find().limit(2).skip(2)
結合排序:db.xyj.find().limit(2).skip(2).sort({age:1}) // 1代表升序,-1代表降序
執行順序: sort > skip > limit
聚合管道
較常見的管道操作符以及他們的作用:
操作符 | 描述 | 語法 |
---|---|---|
$project | 資料投影,主要用於重新命名,增加,刪除欄位 | db.article.aggregate({ $project : {title : 1 ,author : 1 ,}}); |
$match | 過濾,篩選符合條件的文件,作為下一階段輸入 | db.articles.aggregate( [{ $match : { score : { $gt : 70, $lte : 90 } } },{ $group: { _id: null, count: { $sum: 1 } } }] ); |
$limit | 限制經過管道的文件數量 | db.article.aggregate({ $limit : 5 }); |
$skip | 待操作集合處理前跳過部分文件 | db.article.aggregate({ $skip : 5 }); |
$unwind | 將陣列拆分成獨立欄位 | db.article.aggregate({$project:{author:1,title:1,tags:1}},{$unwind:"$tags"}) |
$group | 對資料進行分組 | db.article.aggregate({ $group : {_id : "$author",docsPerAuthor : { $sum : 1 },viewsPerAuthor : { $sum : "$pageViews" }}}); |
$sort | 對文件按照指定欄位排序 | db.users.aggregate( { $sort : { age : -1, posts: 1 } }); |
$sample | 隨機選擇從其輸入指定數量的文件。 | { $sample: { size: <positive integer> } } |
$out | 必須為pipeline最後一個階段管道,因為是將最後計算結果寫入到指定的collection中 | |
$indexStats | 返回資料集合的每個索引的使用情況 | { $indexStats: { } } |
插入測試資料
document1=({name:'dogOne',age:1,tags:['animal','dog'],type:'dog',money:[{min:100},{norm:200},{big:300}]}); document2=({name:'catOne',age:3,tags:['animal','cat'],type:'cat',money:[{min:50},{norm:100},{big:200}]}); document3=({name:'catTwo',age:2,tags:['animal','cat'],type:'cat',money:[{min:20},{norm:50},{big:100}]}); document4=({name:'dogTwo',age:5,tags:['animal','dog'],type:'dog',money:[{min:300},{norm:500},{big:700}]}); document5=({name:'appleOne',age:0,tags:['fruit','apple'],type:'apple',money:[{min:10},{norm:12},{big:13}]}); document6=({name:'appleTwo',age:0,tags:['fruit','apple'],type:'apple',money:[{min:10},{norm:12},{big:13}]}); document7=({name:'pineapple',age:0,tags:['fruit','pineapple'],type:'pineapple',money:[{min:8},{norm:9},{big:10}]}); db.mycol.insert(document1) db.mycol.insert(document2) db.mycol.insert(document3) db.mycol.insert(document4) db.mycol.insert(document5) db.mycol.insert(document6) db.mycol.insert(document7)
假定我們想提取money中min為100的文件,並且只輸出名稱和money陣列中的min那一項
db.mycol.aggregate( {$match:{'money.min':100}}, {$project:{_id:0,name:'$name',minprice:'$money.min'}} )
假定我們想提取money中min小於100的文件,並且限制3個文件,跳過一個文件再顯示
通過type型別來對資料進行分類,並且同時統計他們的年齡age總和
db.mycol.aggregate( {$group:{_id:'$type',sumage:{$sum:'$age'}}} )
按照年齡對資料進行排序
db.mycol.aggregate( {$group:{_id:'$type',sumage:{$sum:'$age'}}}, {$sort:{sumage:1}} )
&n