MongoDB安裝和入門

什麼是MongoDB

MongoDB是一個文檔資料庫,提供好的性能,領先的非關係型資料庫。採用BSON存儲文檔數據。2007年10月,MongoDB由10gen團隊所發展。2009年2月首度推出。MongoDB用c++編寫的。

優勢:
  • 面向文檔的存儲:以 JSON 格式的文檔保存數據。

  • 任何屬性都可以建立索引。

  • 複製以及高可擴展性。

  • 自動分片。

  • 豐富的查詢功能。

  • 快速的即時更新。

  • 來自 MongoDB 的專業支援。

mongodb安裝與啟動

mongodb下載網址: //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}}
)

 

Tags: