mongodb資料庫操作
### 安裝在Ubuntu16.04:
```bash
# 建立資料庫資料夾,這個是預設存放資料的地方,但MongoDB不會自動建立
mkdir -p /data/db
# 增加許可權
chown -R $USER:$USER /data/db
wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | sudo apt-key add - # 匯入公鑰
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list # 為MongoDB建立列表檔案
sudo apt-get update # 重新載入本地資料包
sudo apt-get install -y mongodb-org=4.0.12 mongodb-org-server=4.0.12 mongodb-org-shell=4.0.12 mongodb-org-mongos=4.0.12 mongodb-org-tools=4.0.12 # 安裝軟體包
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections # 保持目前的版本,防止自動更新
# 啟動
sudo service mongodb start #或者
systemctl start mongodb
```
### 解除安裝
```bash
sudo apt-get purge mongodb-org*
sudo rm -r /var/log/mongodb
sudo rm -r /var/lib/mongodb
```
### 通過systemctl start mongodb 啟動時的錯誤解決
報錯如下:
Failed to start mongodb.service: Unit mongodb.service not found.
解決:
```bash
sudo nano /etc/systemd/system/mongdb.service # 建立服務檔案
```
```bash
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target
[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf
# 制定需要執行的命令的位置, # 制定專案執行所需要的配置檔案位置
[Install]
WantedBy=multi-user.target
```
- 按ctrl + x 儲存退出
- systemctl start mongodb
- 永久有效: systemctl enable mongodb
### 1、文件中值的資料型別
在mongodb中資料是以文件的形式存在的
1、每個文件相當於一條記錄
2、多個文件組合在一起,就是集合,一個集合就相當於一張資料表
3、多個集合組合在一起,就是資料庫,每個資料庫就是一個資料夾
- Object ID: ⽂檔ID
- String: 字串, 最常⽤, 必須是有效的UTF-8
- Boolean: 儲存⼀個布林值, true或false
- Integer: 整數可以是32位或64位, 這取決於伺服器
- Double: 儲存浮點值
- Arrays: 陣列或列表, 多個值儲存到⼀個鍵
- Object: ⽤於嵌⼊式的⽂檔, 即⼀個值為⼀個⽂檔
- Null: 儲存Null值
- Timestamp: 時間戳, 表示從1970-1-1到現在的總秒數
- Date: 儲存當前⽇期或時間的UNIX時間格式
### 2、Mongo shell
- 使用mongo命令自動啟動shell,並連線資料庫伺服器,該shell能夠解析JavaScript的語法
- 通過shell可以完成一些列的增刪改查工作
### 3、文件的基本增刪改查
- 增加:使用insert()函式,將要插入的資料放到集合中
- 比如增加一個文件,首先先建立文件變數
post = {"title": "my first mongo"}
- 插入文件到blog集合中
db.blog.insert(post)
- 批量插入:同樣適用inset方法,將你需要插入的文件全部存放到一個陣列中
- 當我們連線到伺服器之後,**db**會自動指向正在使用的資料庫,blog為集合名,沒有會自動建立
- 查詢:使用find()或者findOne()
- find()預設顯示20條資料
db.blog.find()
- findOne()只顯示一條資料
db.blog.findOne()
- 更新:使用**update()**方法, 該方法接收兩個引數,第一個為需要修改的文件,第二個修改過的文件
**update()方法除了接收前兩個引數外,還可以接收另外兩個引數,並且這兩個引數都是布林值**
**例如:db.blog.update({"title": "My Blog Post"}, {"title": "My Blog Get"}, true, true)**
**第三個參數列示upsert,能夠保證操作的原子性,同時在沒有查詢到制定的集合情況下,會以查詢條件和更新文件為基礎新建一個文件,第四個引數預設是true,表示更新所有符合條件的集合,若改為false,則只更新第一個。**
- 第一:先更改文件物件的屬性,也就是鍵值對,比如前文使用到的post變數
給他增加一個屬性:post.comments = []
- 找到舊文件,替換為新的文件,根具給出的一個引數中的具體資訊可以找到舊文件
db.blog.update({"title":"my first mongo"}, post)
- 刪除:remove(),在不給出引數的情況下,刪除集合中的所有文件,給出引數後,會刪除對應的文件
- db.blog.remove({"title":"my first mongo"})
### 4、基於shell的其他命令,利用help檢視
```shell
> help
```
| db.help() | help on db methods |
| -------------------------- | --------------------------------------------------------- |
| db.mycoll.help() | help on collection methods |
| sh.help() | sharding helpers |
| rs.help() | replica set helpers |
| help admin | administrative help |
| help keys | key shortcuts |
| help connect | connecting to a db help |
| help misc | misc things to know |
| help mr | mapreduce |
| show dbs | show database names |
| show collections | show collections in current database |
| show users | show users in current database |
| show profile | show most recent system.profile entries with time >= 1ms |
| show logs | show the accessible logger names |
| use <db_name> | set current database |
| db.foo.find() | list objects in collection foo |
| db.foo.find( { a : 1 } ) | list objects in foo where a == 1 |
| it | result of the last line evaluated; use to further iterate |
| DBQuery.shellBatchSize = x | set default number of items to display on shell |
| exit | quit the mongo shell |
### 5、訪問集合
1、當集合名與內建的函式名相同時,是沒有辦法通過**db.集合名**來訪問的
2、當集合名名包含**-**時,比如:**six-four**,同樣沒有辦法通過正常的方法訪問集合,引文shell對其的解釋是兩個變數的相減
**最終的解決辦法是通過__getCollection()__來訪問,**例如:db.getCollection("version"),db.getCollection("six-four")這樣才能正常訪問
### 6、save shell
save是一個shell函式,可以在文件不存在的時候插入,存在的時候更新,它只有一個引數,即文件本身
save會呼叫upsert,即實現文件的自動建立和更新
var x = db.foo.findOne()
x.num = 12
db.foo.save(x)
### 7、修改器,以$號開頭的特殊字串
| 修改器 | 用法 | 作用 |
| ---- | :--- | :--- |
| $inc | db.x.update({"a":1}, {$inc: {"b":1}}) |在原有b的基礎上加1|
| $set | db.x.update({"a":1}, {$set: {"b":"a"}}) |將原有b的資料修改為a,若b不存在,則建立一個|
| $unset | db.x.update({"a":1}, {$unset: {"b":1}}) |撤銷修改,此時的數值1,表示條件為真的意思|
| $push | db.x.update({"a":1}, {$push:{"comments": {"name":"json"}}}) |該修改器只作用於陣列,可以向文件中已有陣列中新增值,當然陣列不存在時,建立一個陣列並新增對應內容|
| $pop | db.x.update({"a":1}, {$pop:{"comments": 1}}) db.x.update({"a":1}, {$pop:{"comments": -1}}) |基於陣列位置的刪除,1表示從陣列的尾部刪除一個元素,-1表示從陣列的頭部刪除一個元素|
| $addToSet | db.x.update({"a":1}, {$addToSet:{"email": "aa@163.com"}) |該修改器只作用於陣列,可以向陣列中新增一個值,若陣列中已經有了該值,則新增失敗|
| $each | db.x.update({"a":1}, {$addToSet:{"email": {$each: ["1", "2", "3"]}}) |可以遍歷出陣列中的每個值,通常與$addToSet搭配使用,完成多個值得新增,如果存在不新增|
| $pull | db.x.update({"a":1}, {$pull:{"email": "1"}}) |指定陣列中的具體元素進行刪除,若匹配到多個值,匹配多少刪除多少|
| $陣列定位符 | db.x.update({"comments.author": "jhon"}, {$set:{"comments.$.author": 'lili'}}) |定位符只匹配第一個匹配到的文件|
### 8、查詢
#### 8.1、指定鍵返回查詢
- 查詢使用find函式或者findOne函式
- 查詢返回指定欄位,也就是查詢指定鍵
- db.blog.find({"a":2}, {"ss":1, "wo": 0}),當匹配到包含{"a":2}的文件後,只返回"_id" 和"ss"兩個鍵,"_id"是預設返回的,其中1表示真,0表示假
#### 8.2、條件查詢
| 命令 | 用法 | 作用 |
| ------- | ----------------------------------------------------------- | ------------------------------------------------------------ |
| $gt | db.users.find({"age": {"$gt": 20}}) | 查詢users集合中年齡大於20的文件 |
| $gte | db.users.find({"age": {"$gte": 20}}) | 查詢users集合中年齡大於等於20的文件 |
| $lt | db.users.find({"age": {"$lt": 20}}) | 查詢users集合中年齡小於20的文件 |
| $lte | db.users.find({"age": {"$lte": 20}}) | 查詢users集合中年齡小於等於20的文件 |
| $ne | db.users.find({"username": {"$ne": "andy"}}) | 查詢users集合中使用者名稱不等於andy的文件 |
| $or | db.users.find({"$or": [{"age": 20},{"username": "andy"} ]}) | $or 鍵對應的值是一個陣列,滿足陣列中任何一個條件的文件都會被查詢出來,可作用於不同的鍵 |
| $in | db.users.find({"age": {"$in": [12 ,10, 22]}}) | $in鍵對應的值是一個陣列,滿足陣列中任何一個條件的文件都會被查詢出來,但是它只作用於同一個鍵 |
| $nin | db.users.find({"age": {"$nin": [12 ,10, 22]}}) | $nin鍵對應的值是一個陣列,不滿足陣列中任何一個條件的文件都會被查詢出來,它也只作用於同一個鍵 |
| $mod | db.users.find({"age": {"$mod": [5, 1]}}) | $mod表示取模運算,運算完成後在作為查詢條件,它對應的值是一個陣列,該陣列只有兩個值且有順序,第一個表示除數,第二個表示餘數,在這裡表達的意思是,找出年齡除以5後餘數為1的文件 |
| $not | db.users.find({"$not":{"age": {"$mod": [5, 1]}}}) | $not是元條件查詢,即作用其他條件查詢之上,例如他與$mod取模運算結合使用,表示取非 |
| $existe | db.users.find({"x":{"$existe": true}}) | $existe判斷該鍵是否真實存在,存在則顯示出來 |
| /joy/i | db.users.find({"username": /joy/i}) | 這裡是利用正規表示式去匹配所查詢文件的某個鍵對應的值,i表示不區分大小寫 |
$where 自定義查詢
```js
db.stu.find({
$where:function() {
return this.age>30;} // this 代表當前查詢的文件,找出年齡大於30歲的文件
})
```
#### 8.3、陣列查詢
##### 8.3.1、$all
- 建立如下集合並加入三條文件:
db.fruit.insert({"_id": 1, "fruits": ["banana", "peach", "apple"]})
db.fruit.insert({"_id": 2, "fruits": ["orange", "kumquat", "apple"]})
db.fruit.insert({"_id": 3, "fruits": ["banana", "cherry", "apple"]})
- {"$all": ["banana", "apple"]},作用於陣列,
使用db.fruit.find({"fruits": {"$all" : ["banana", "apple"]}}),執行結果是數值fruits中只要包含有"banana"和"apple"元素的文件,全部返回,忽略陣列中元素的順序
- 特殊用法
{"fruits": {"$all" : ["banana"]}}和{"fruits":"banana"},這兩條查詢效果是一樣的
- 基於陣列下標的查詢
比如:db.fruit.find({"fruits.2":"apple"}),只要陣列中指定位置的元素匹配正確,就會返回結果
##### 8.3.2、$size
- 查詢固定陣列長度的文件
- 用法:db.fruit.find({"fruits": {"$size": 3}})
- 不能配合其他條件命令使用,例如$gt,而實際生產中,總是需要我們去查詢陣列範圍的文件
- 在文件中建立一個size的欄位來專門描述陣列的長度,變相的通過size的值來範圍查詢
- 例如上文:增加一個size欄位,db.fruit.update({"_id": 1}, {"$inc": {"size": 3}})
- 增加陣列的內容時,同時增加size的值
db.fruit.update({"_id": 1}, {"$push" : {"fruits": "pear"}, "$inc" : {"size": 1}})
- 最後就可以進行範圍查詢了
db.fruit.find({"size": {"$gt": 3}})
##### 8.3.3、$slice
- 對查詢到的陣列進行切片處理,並返回新的切片後的文件
- 使用$slice必須配合find函式的第二個引數使用,find的第二引數是指定文件中的鍵返回的,未提及或者對應值為0,將不會被返回,當使用$slice後,即使不提及文件中的其他鍵同樣會返回
```mongo
db.fruit.find({"_id" : 1}, {"fruits": 1})
>{ "_id" : 1, "fruits" : [ "banana", "peach", "apple", "pear"]} # 這裡_id預設返回
# 如果將_id的值變為0,則不會被返回
db.fruit.find({"_id" : 1}, {"fruits": 1, "_id": 0}) # 數字代表真假
>{"fruits" : [ "banana", "peach", "apple", "pear"]}
# 當對返回的鍵使用切片後$slice,文件中所有的鍵預設都會返回
db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}})
>{ "_id" : 1, "fruits" : [ "banana", "peach", "apple" ], "size" : 4 }
```
- 對陣列正向切割
db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}}), $slcie對應的值是正數即可,得到陣列的前三個元素
- 對陣列反向切割
db.fruit.find({"_id": 1}, {"fruit": {"$slice": -3}}), $slcie對應的值是負數即可,得到陣列的後三個元素
- 對陣列指定範圍切片
db.fruit.find({"_id": 1}, {"fruit": {"$slice": [1, 3]}}),$slice對應的值為陣列,該陣列表示你要操作的陣列下標
,得到結果:**{ "_id" : 1, "fruits" : [ "peach", "apple", "pear" ], "size" : 4 }**,包含起始和結束下標
#### 8.4、查詢內嵌文件
- 在mongodb中文件的表現形式,像極了javascript中的物件,所以可以通過**物件.屬性**的方法,來訪問MongoDB中的內嵌文件,但也可以匹配整個內嵌文件
- 方法一:如有文件
{"name": {"first": "Joe", "last": "Schmoe"}, "age": 27},在集合people中
db.people.find({"name": {"first": "Joe", "last": "Schmoe"}}),這裡可以找到有這個內嵌文件的文件,但是有一個缺點,就是查詢條件必須匹配整個內嵌文件,否則就會匹配失敗,同時順序也不能夠錯,也就是要求精確匹配
- 方法二:通過**物件.屬性**的方法來訪問,就不存在限制了
db.people.find({"name.first": "Joe", "name.last": "Schmoe"}),這裡就要求精確匹配了
- $elemMatch
將限定條件進行分組,僅當需要對一個內嵌文件的多個鍵操作時才會用到
db.blog.find({"comments": {"$elemMatch": {"author": "joe", "score": {"$gte": 5}}}})
### 9、排序、分頁和跳過
#### 9.1、排序sort
- 使用方法:db.collection.find().sort({"username": 1})
- 返回結果按升序排列,同時可以設定多個鍵排序
db.collection.find().sort({"username":1, "age": -1})
先以username升序排列,若username相同,則按照age降序排列
#### 9.2、分頁limit
- 使用方法:
db.collection.find().limit(20),表示每頁返回20條資料
#### 9.3、跳過skip
- db.collection.find().skip(20),跳過前20個資料
**組合實現分頁查詢**
- db.collection.find().limit(20).sort({"age": -1})
按照年齡從大到小取出前二十條文件
- db.collection.find().limit(20).skip(20).sort({"age": -1})
跳過前20條,取後20條的結果
### 10、建立索引
- 方法:db.users.ensureindex({"username": 1})
### 11、遊標物件
使用find函式返回的物件可以賦值給一個變數,這個變數就可以理解為是一個遊標物件
**遊標物件屬性** :可迭代(iterable)
**遊標物件方法** :hasNext()判斷是否還有下一條資料
next()獲取下一條資料
### 12、聚合函式(aggregate)
#### 12.1、count函式
db.stu.count() # 返回fruit集合中的總文件數
現有如下集合mycol:
```javascript
{ "_id" : 1, "name" : "tom", "sex" : "男", "score" : 100, "age" : 34 }
{ "_id" : 2, "name" : "jeke", "sex" : "男", "score" : 90, "age" : 24 }
{ "_id" : 3, "name" : "kite", "sex" : "女", "score" : 40, "age" : 36 }
{ "_id" : 4, "name" : "herry", "sex" : "男", "score" : 90, "age" : 56 }
{ "_id" : 5, "name" : "marry", "sex" : "女", "score" : 70, "age" : 18 }
{ "_id" : 6, "name" : "john", "sex" : "男", "score" : 100, "age" : 31 }
```
#### 12.2、$group,$sum
db.stu.aggregate({$group:{_id: "$sex", Count: {"$sum": 1}}})
#### 12.3、$group,$push
```json
db.stu.aggregate(
{$group:
{
_id:"$gender",
name:{$push:"$name"}
}
}
) 把所有的資料放到一起
$$ROOT, 把整個文件放到一個陣列中
db.stu.aggregate(
{$group:
{
_id:null,
name:{$push:"$$ROOT"}
}
}
)
```
#### 12.4、$match`
```json
db.stu.aggregate(
{$match:{age:{$gt:20}}
)
```
#### 12.5、$project
```json
db.stu.aggregate(
{$project:{_id:0,name:1,age:1}}
) //控制顯示的文件鍵
```
#### 12.6、$sort
```json
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$sort:{counter:-1}}
)
```
#### 12.7、$limit,$skip
```json
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$sort:{counter:-1}},
{$skip:1},
{$limit:1}
)
```
### 13、資料庫命令(runCommand)
#### 13.1、distinct函式
db.runCommand({"distinct": "fruit" , "key": "fruits"})
runCommand指令表示執行命令,括號內的引數的第一個鍵為具體的指令,指令所對應的的值是要操作的集合,key對應的是要操作的鍵。
distinct所表達的意思是找出集合中某個鍵對應多少不同的值,也就是去重。
#### 13.2、group函式
- 對文件進行分組,stocks集合中有以下文件:
db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 03:57:01 GMT-400", "price": "4.23"})
db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 11:28:39 GMT-400", "price": "4.27"})
db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 05:00:22 GMT-400", "price": "4.10"})
db.stock.insert({"day" : "2010/10/06", "time": "10/06/2010 05:27:58 GMT-400", "price": "4.30"})
db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 08:34:50 GMT-400", "price": "4.01"})
獲取到每天最新的股票交易價格
- 使用資料庫命令的模式來執行group命令:
```javascript
db.runCommand({"group":{
"ns": "stock",
"key": {"day": true}, // 程式執行到這裡之後,就已經對集合分組完畢了
"$keyf": function(X){
return X.toLowerCase() // 將需要排序的鍵進行轉換,比如進行大小寫轉換
},
"initial":{"time":0}, // 每組文件遍歷時候的初始值
"$reduce":function(doc, prev){
if(doc.time>prev.time){ // 判斷時間大小,更新要顯示的最近時間
prev.time = doc.time;
prev.price= doc.price;
}
},
"condition": {"day": {"$gt": "2010/10/03"}},// 對分組進行條件限制,必須大於條件時間
"finalize":function(prev){ //對返回結果做最後的修改,和限定
...
}
}})
```
**引數解析**
group:對集合執行的操作,即分組
ns:需要操作的資料集
key:以文件中的哪個鍵進行分組
$keyf: 對需要分組的鍵進行條件轉換
initial: 每組文件的初始化值,也就是最終分完組後顯示的欄位的初始化值
$reduce: 對分組後的顯示文件做最後的操作,在上述案例中,就是找到那一組文件中時間最新的文件,然後把他的時間和股票交易價格顯示到我們可以看到的結果
condition: 對分組進行條件限制
finalize: 對返回的結果做最後的修改
#### 13.3、findAndModify
db.runCommand({"findAndModify": "stock", # 操作集合stock
"query": {"day":{"$gt": "2010/09/30"}}, # 查詢條件
"sort": {"day": -1}, # 排序鍵
"remove": true # 是否刪除文件true
})
#### 13.4、建立固定大小的集合
db.creatCollection("my_collection",{"capped": true, "size": 100000})
**引數解析**
my_collection:集合名
capped:表示是否限值集合的大小,true表示限值,false表示不限制
size:表示集合大小,這裡表示100000個位元組
相關文章
- MongoDB 資料庫操作MongoDB資料庫
- nodejs操作mongodb資料庫(mongodb)NodeJSMongoDB資料庫
- MongoDB資料庫基礎操作MongoDB資料庫
- python操作mongodb資料庫PythonMongoDB資料庫
- Python操作MongoDB文件資料庫PythonMongoDB資料庫
- MongoDB資料庫的基本操作梳理MongoDB資料庫
- Python資料庫MongoDB騷操作Python資料庫MongoDB
- Python 資料庫騷操作 -- MongoDBPython資料庫MongoDB
- ASP.NET MongoDB資料庫操作類ASP.NETMongoDB資料庫
- MongoDB資料庫操作詳解:基礎篇MongoDB資料庫
- node 使用 monk 工具操作 mongodb 資料庫學習MongoDB資料庫
- MongoDB資料庫MongoDB資料庫
- MongoDB之資料增加操作MongoDB
- Python3.5使用pymongo(3.3.1)操作mongodb資料庫PythonMongoDB資料庫
- Eolink Apikit :資料字典功能上線、支援 MongoDB 資料庫操作...APIMongoDB資料庫
- MongoDB之資料查詢操作MongoDB
- python資料庫-mongoDB的高階查詢操作(55)Python資料庫MongoDB
- 常見MongoDB資料庫操作產生的鎖總結MongoDB資料庫
- mongodb資料庫中插入資料MongoDB資料庫
- 初試MongoDB資料庫MongoDB資料庫
- mongodb 如何建立資料庫MongoDB資料庫
- 快速掌握 MongoDB 資料庫MongoDB資料庫
- MongoDB資料庫安裝MongoDB資料庫
- 學習MongoDB資料庫MongoDB資料庫
- mongoDB資料庫之聚合MongoDB資料庫
- MongoDB資料庫備份MongoDB資料庫
- MongoDB資料庫入門MongoDB資料庫
- MongoDB資料庫簡介MongoDB資料庫
- Mongodb資料庫連線MongoDB資料庫
- 資料庫——MongoDB——>Java篇資料庫MongoDBJava
- MongoDB資料庫效能分析MongoDB資料庫
- 啟動MongoDB資料庫MongoDB資料庫
- 資料庫_SQL-MongoDB資料庫SQLMongoDB
- 常用操作 / 資料庫操作資料庫
- 資料庫操作資料庫
- 資料庫操作·資料庫
- TSPython操作MySQL MongoDB Oracle三大資料庫深入對比oeePythonMySqlMongoDBOracle大資料資料庫
- mongodb資料庫如何建立索引?MongoDB資料庫索引