[TOC]
# 文檔
文檔是mongoDB中數據的基本單元,類似關系數據庫的行,
多個鍵值對有序地放置在一起便是文檔。
MongoDB 中以文檔的方式存取記錄,如一條記錄格式如下:
~~~
{ “username”:”Tom”, “age”:10 ,email:’xiaobai@sohu.com’,’sex’:男,鍵,值}
{ "username":"Tom" , "age" : "10" }
{“Username”:”Tom”,”age”:10}
{“Username”:”Tom” }
~~~
注意:
(1)以上是幾個不同的文檔,MongoDB區分大小寫的數據類型,第一個age字段是數字類型,第二個age是字符串類型。
(2)每一個文檔尺寸不能超過16M
# 集合
集合就是一組文檔,多個文檔組成一個集合,集合類似于 mysql里面的表 。
無模式是指,在同一個集合中可以包含不同格式的文檔,如:
~~~
{ "Name" : "Mongodb" , "Type" : "Nosql" }
{ "UserName" : "Tom" , "age" : 20 , "Gender" : "male" }
~~~
以上兩個文檔可以放在同一個集合中。
在Mysql需要先建表再插入數據,
模式自由(schema-free):意思是集合里面沒有行和列的概念,
注意:MongoDB中的集合不用創建、沒有結構,所以可以放不同格式的文檔。
# 數據庫
多個集合可以組成數據庫。一個mongoDB實例可以承載多個數據庫,他們之間完全獨立。
Mongodb中的數據庫和Mysql中的數據庫概念類似,只是**無需創建**。
一個數據庫中可以有多個集合。
一個集合中可以有多個文檔。
# 數據體系

# 入門語句
** 創建數據庫**
如果該數據庫不存在,則創建,如果該數據庫存在,則是切換,如果創建了數據庫,沒有任何的操作,則會自動刪除該數據庫。
~~~
use app
~~~
**查看數據庫**
~~~
show dns
~~~
**創建集合**
注意:mongodb里面的集合是隱式創建,就是無需創建,直接使用。
語法:`db.集合名.insert({})`該語法意思是,向集合里面,添加文檔

**查看集合**
`show tables`
**查詢集合里面的文檔**
~~~
db.集合名.find() 查詢所有
db.集合名.findOne() 查詢第一個文檔
~~~
**刪除集合**
~~~
db.集合名.drop();
~~~
**刪除數據庫**
~~~
use 數據庫
db.dropDatabase()
~~~
# 增刪改查
## 增加
~~~
db.集合名.insert({k1:’v1’,k2:’v2’…..})
~~~
~~~
db.class1.insert({k1:'v1', k2:'v2'})
~~~
注意點:
(1)文檔就是鍵值對,數據類型是BSON格式,支持的值更加豐富。
比如:`db.集合名.insert({name:’xiaobai’,spc:{weight:100,address:’guangzhou’}})`
(2)在添加的文檔里面,都有一個’_id’的鍵,值為對象類型。
ObjectId類型:
每個文檔都有一個`_id`字段,并且同一集合中的_id值唯一,該字段可
以是任意類型的數據,默認是一個ObjectId對象。
ObjectId對象對象數據組成:`時間戳 |機器碼|PID|計數器 `
_id的鍵值我們可以自己輸入,但是不能重復
注意:在插入數據的時候,如果_id的值重復則會報錯。

(3) 可以使用js代碼來完成批量插入文檔。

## 刪除
語法:db.集合名.remove({條件})(不寫條件刪除所有的文檔)
例1:刪除 php 集合中年齡等于5的文檔
~~~
db.user.remove({age:5})
~~~
## 更新文檔
方法一,直接修改
語法:db.集合名.update({條件},{新的文檔},是否新增,是否修改多條)
語法: db.集合.update(條件,新文檔, 是否新增, 是否修改多條)
是否新增:如果值是1(true)則沒有滿足條件的則添加。
是否修改多條:若值是1(true),如果滿足條件的有多個文檔則都要修改,
案例1:在php集合里面,要修改age=4的文檔名稱為xiaosi
~~~
db.php.update({age:4},{name:’xiaosi’})
~~~

注意;以上修改方式,會丟失其他的鍵值,因此不推薦使用
案例2:要修改age=3的文檔名稱為xiaosan,并且其他鍵值不能丟失
使用修改器
`$inc` : 加一個數字
`$set` : 修改某一個字段,如果該字段不存在就增這個字段
語法:`db.集合名.update({條件},{修改器名稱:{修改的鍵:修改的新值}})`
~~~
db.user.update({age:3},{'$set':{name:'xiaosan'}})
~~~
案例3:要修改age=1的文檔的年齡添加10歲
語法:`db.集合名.update({條件},{修改器名稱:{修改的鍵:修改的新值}})`
~~~
db.user.update({age:1},{'$inc':{age:10}})
~~~

## 查詢文檔
語法:`db.集合名.find({條件})`
案例1:取出php集合里面第一個文檔
~~~
db.user.findOne();
~~~
案例2:取出php集合里面age=2的文檔
~~~
db.user.find({age:2})
~~~
案例3:取出php集合里面age大于2的文檔
~~~
db.user.find({age:{‘$gt’:2}})
~~~
案例4:取出php集合里面的文檔,只顯示name鍵
~~~
db.user.find({},{name:1})//1表示只顯示name鍵值
~~~
注意:`db.php.find({},{age:0})//0表示除了age鍵值,其他的都顯示。`
案例5:根據年齡的(降序|升序)來顯示文檔
~~~
db.集合名.find().sort({age:1})根據年齡升序
db.集合名.find().sort({age:-1})根據年齡降序
~~~
案例6:顯示php集合中前3個文檔。
~~~
db.user.find().limit(3)
~~~
案例7:顯示php集合中第3個文檔到第5個文檔。
~~~
db.user.find().skip(2).limit(5) 相當于 mysql里面的 limit offset number
~~~
案例8:統計php集合中文檔的個數
~~~
db.集合名.count():返回集合中有多少個文檔。
~~~
## 常用操作符
~~~
$lt , $lte , $gt , $gte ( < , <= , > , >= ), $ne ( <> ) ,$in , $nin , $or , $not,
$mod (取模), $exists, $where
db.php.remove({age:{‘$gt’:8}})
~~~
# 權限
在mongodb里面的用戶是屬于數據庫的,每個數據庫有自己的管理員,管理員登錄后,只能操作所屬的數據庫。
注意:一般在admin數據庫中創建的用戶授予超級管理員權限,登錄后可以操作任何的數據庫。

## 創建超級管理員
注意:在開啟權限管理控制時,一定先要創建一個超級管理員授予超級管理權限。
登錄mongodb的客戶端,使用如下命令
~~~
use admin
db.createUser({ user:'root', pwd:'123456', roles:[{role:'root',db:'admin'}] })
~~~
## 修改mongodb數據庫配置文件
~~~
MongoDB\Server\4.0\bin
security:
authorization: enabled
~~~

## 重啟mongodb服務
連接數據庫
如果沒有輸入密碼,進入 MongoDB的客戶端,進行操作,會報如下錯誤提示;

本地連接:
~~~
mongo 數據庫名稱 -u 用戶名 -p 密碼
mongo admin -u 用戶名 -p 密碼
~~~
~~~
遠程連接:mongo IP地址:端口/數據庫名稱 -u 用戶名 -p 密碼
~~~
## 給php創建個普通管理員
~~~
use php
db.createUser( { user: "phpadmin", pwd: "123456", roles: [ { role: "dbOwner", db: "php" } ] } )
~~~
登錄操作

## 常用命令
~~~
show users; #查看當前庫下的用戶
~~~
~~~
db.dropUser("eggadmin") #刪除用戶
db.updateUser( "admin",{pwd:"password"}); #修改用戶密碼
db.auth("admin","password"); #密碼認證
~~~

# 數據庫角色
(1)數據庫用戶角色:read、readWrite;
(2)數據庫管理角色:dbAdmin、dbOwner、userAdmin;
(3)集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
(4)備份恢復角色:backup、restore;
(5)所有數據庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、 dbAdminAnyDatabase
(6)超級用戶角色:root
# 索引
索引是對數據庫表中一列或多列的值進行排序的一種結構,可以讓我們查詢數據庫變得 更快。MongoDB 的索引幾乎與傳統的關系型數據庫一模一樣,這其中也包括一些基本的查 詢優化技巧。
## 普通單列索引
~~~
db.集合名.ensureIndex({name:1})
~~~
語法:
~~~
db.集合名.ensureIndex({鍵名:1}) 1是升續 -1是降續
~~~
## 多列索引(復合索引)
創建多列索引
~~~
db.集合名.ensureIndex({field1:1/-1, field2:1/-1});
~~~
對name和age 建立一個復合索引
可以使用db.集合名.getIndexes()查看創建的索引情況

該索引被創建后,基于 username 和 age 的查詢將會用到該索引,或者是基于 username 的查詢也會用到該索引,但是只是基于 age 的查詢將不會用到該復合索引。因此可以說, 如果想用到復合索引,必須在查詢條件中包含復合索引中的前 N 個索引列
## 子文檔索引
語法:
~~~
db.集合名.ensureIndex({filed.subfield:1/-1});
~~~
如下文檔可以建立子文檔索引
~~~
{name:’諾基亞手機1’,price:12.34,spc:{weight:100,area:’紐約’}}
{name:’諾基亞手機2’,price:42.34,spc:{weight:200,area:’倫敦’}}
~~~
比如要查詢weight等于100的文檔。
~~~
db.goods.find({‘spc.weight’:100})
~~~
根據當前案例,我們建立子文檔索引
~~~
db.集合名.ensureIndex({'spc.w':1})
~~~

## 唯一索引
~~~
db.集合名.ensureIndex({name:-1},{unique:true})
~~~


## 查看索引
常用命令:
(1)查看當前索引狀態: `db.集合名.getIndexes(); `
(2)詳情查看本次查詢使用哪個索引和查詢數據的狀態信息。
explain executionStats 查詢具體的執行 時間
~~~
db.tablename.find().explain( "executionStats" )
~~~
關注輸出的如下數值:`explain.executionStats.executionTimeMillis`

有索引時,查詢時間;

刪除索引時查詢時間

## 刪除索引
刪除單個索引
~~~
db.集合名.dropIndex({filed:1/-1});
~~~
刪除所有索引
~~~
db.集合名.dropIndexes();
~~~
注意:在刪除所有的索引時,主鍵索引會保留。
## 重建索引
一個表經過很多次修改后,導致表的文件產生空洞,索引文件也如此.
可以通過索引的重建,減少索引文件碎片,并提高索引的效率.
類似mysql中的`optimize table `
mysql里面使用optimize table語法:optimize table 表名
~~~
語法:db.集合名.reIndex()
~~~
## 索引使用注意
(1)創建索引的時候,注意1是正序創建索引 \-1是倒敘創建索引
(2)索引的創建在提高查詢性能的同時會影響插入性能,對于經常查詢少插入的文檔可以考慮用索引
(3)復合索引要注意索引的先后順序。
(4)每個鍵全建立索引不一定就能提高性能,索引不是萬能的。
(5)在做排序工作的時候如果是超大數據量也可以考慮加上索引用來提高排序的性能。
# 數據導入導出
導入/導出可以操作的是本地的mongodb服務器,也可以是遠程的,所以,都有如下通用選項。
利用mongoexport
~~~
-h host主機
--port 端口
-d 指明使用的庫
-c 指明要導出的集合
-o 指明要導出的文件名
--csv指定導出的csv格式
-q 過濾導出
-f field1 field2 列名
-u username 用戶名
-p password 密碼
~~~
如下操作,
注意:如果端口是默認的可以不使用--port來指定端口。
比如我們要導出php庫下面的Java集合,
~~~
E:\Program Files\MongoDB\Server\4.0\bin>mongoexport -h localhost -d php -c java -o e:/nihao.json -u phpadmin -p 123456
~~~
導出文件內容如下

導入
使用mongoimport命令
~~~
-d 待導入的數據庫
-c 待導入的集合(不存在會自己創建)
--type csv/json(默認)
--file 備份文件名稱包含路徑
~~~
~~~
例1: 導入json
./bin/mongoimport -h --port 端口號 -d test -c goods --file ./goodsall.json
例2: 導入csv
./bin/mongoimport -h --port 端口號 -d test -c goods --type csv -f goods_id,goods_name --file ./goodsall.csv
./bin/mongoimport -h --port 端口號 -d test -c goods --type csv --headline -f goods_id,goods_name --file ./goodsall.csv
案例:把剛才導出的nihao.json文件導入到php庫里面的user集合里面。
E:\Program Files\MongoDB\Server\4.0\bin>mongoimport -h localhost -d php -c nihao --file e:/nihao.json -u phpadmin -p 123456
~~~
# 主從復制(讀寫分離)
主從復制是一個簡單的數據庫同步備份的集群技術。
1、原理圖:
2、實現的注意點;
(1)在數據庫集群中要明確的知道誰是主服務器,主服務器只有一臺。
(2)從服務器要知道自己的數據源也就是對于的主服務是誰。
(3)--master用來確定主服務器,--slave和--source來控制從服務器。

具體的配置步驟
(1)啟動主服務器
~~~
--port --dbpath –logpath --master
~~~

(2)啟動從服務器
~~~
--port –dbpath –logpath –slave –source 127.0.0.1:1111
~~~

(3)客戶端登陸到主服務器
添加一些數據,測試是否同步到從服務器
如下在主服務器里面,添加了一些文檔
第一步:客戶端登錄到主服務器,添加一些文檔
~~~
mongo localhost:1111
~~~

第二步:登陸到從服務器,查看是否有數據
~~~
mongo localhost:2222
~~~
如果有數據,則成功了
# php操作
## 插入數據
~~~
$manager = new MongoDB\Driver\Manager("mongodb://phpadmin:123456@localhost:27017/php");
//插入數據
//創建一個對象
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(['name'=>'劉備','age'=>12,'email'=>'liubei@sohu.com']);
$bulk->insert(['name'=>'關羽','age'=>22,'email'=>'guanyu@sohu.com']);
$bulk->insert(['name'=>'張飛','age'=>18,'email'=>'zhangfei@sohu.com']);
$manager->executeBulkWrite('php.stu', $bulk);
echo 'ok';
~~~
## 查詢數據
~~~
$filter = ['age'=>['$gt'=>16]];
$options = [
'projection'=>['_id'=>0],
'sort'=>['age'=>1]
];
$query = new MongoDB\Driver\Query($filter, $options);
//$query = new MongoDB\Driver\Query([],[]);
$data = $manager->executeQuery('php.stu', $query);
echo '<pre>';
foreach ($data as $key => $value) {
print_r($value);
}
~~~
## 更新數據
~~~
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
['age' => 12],
['$set' => ['name' => '劉備被', 'email' => 'liubeibei@sohu.com']],
['multi' => false, 'upsert' => false]
);
$writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$result = $manager->executeBulkWrite('php.stu', $bulk, $writeConcern);
echo 'ok';
~~~
## 刪除數據
~~~
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->delete(['age' => 22], ['limit' => 1]); // limit 為 1 時,刪除第一條匹配數據
//$bulk->delete(['x' => 2], ['limit' => 0]); // limit 為 0 時,刪除所有匹配數據
$writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 1000);
$result = $manager->executeBulkWrite('php.stu', $bulk, $writeConcern);
var_dump($result);
~~~
# linux
linux系統安裝mongodb
解壓后,直接進入目錄啟動即可;在啟動時要添加`--fork`參數,作為一個進程后臺運行


- 配置
- composer安裝
- composer用法
- composer版本約束表達
- phpstorm
- sftp文件同步
- php類型約束
- laradock
- 配置文件緩存詳解
- git
- 自定義函數
- 核心概念
- IOC
- 服務提供者
- Facade
- 契約
- 生命周期
- 路由
- 請求
- 命名路由
- 路由分組
- 資源路由
- 控制器路由
- 響應宏
- 響應
- Command
- 創建命令
- 定時任務
- console路由
- 執行用戶自定義的定時任務
- artisan命令
- 中間件
- 創建中間件
- 使用中間件
- 前置和后置
- 詳細介紹
- 訪問次數限制
- 為 VerifyCsrfToken 添加過濾條件
- 單點登錄
- 事件
- 創建
- ORM
- 簡介
- DB類
- 配置
- CURD
- queryScope和setAttribute
- 查看sql執行過程
- 關聯關系
- 一對一
- 一對多
- 多對多
- 遠程關聯
- 多態一對多
- 多態多對多
- 關聯數據庫的調用
- withDefault
- 跨模型更新時間戳
- withCount,withSum ,withAvg, withMax,withMin
- SQL常見操作
- 模型事件
- 模型事件詳解
- 模型事件與 Observer
- deleted 事件未被觸發
- model validation
- ORM/代碼片段
- Repository模式
- 多重where語句
- 中間表類型轉換
- Collection集合
- 新增的一些方法
- 常見用法
- 求和例子
- 機場登機例子
- 計算github活躍度
- 轉化評論格式
- 計算營業額
- 創建lookup數組
- 重新組織出表和字段關系并且字段排序
- 重構循環
- 其他例子
- 其他問題一
- 去重
- 第二個數組按第一個數組的鍵值排序
- 搜索ES
- 安裝
- 表單
- Request
- sessiom
- Response
- Input
- 表單驗證
- 簡介
- Validator
- Request類
- 接口中的表單驗證
- Lumen 中自定義表單驗證返回消息
- redis
- 廣播事件
- 發布訂閱
- 隊列
- 守護進程
- redis隊列的坑
- beanstalkd
- rabbitmq
- redis隊列
- 日志模塊
- 錯誤
- 日志詳解
- 數據填充與遷移
- 生成數據
- 數據填充seed
- migrate
- 常見錯誤
- Blade模板
- 流程控制
- 子視圖
- URL
- 代碼片段
- Carbon時間類
- 一些用法
- 郵件
- 分頁
- 加密解密
- 緩存
- 文件上傳
- 優化
- 隨記
- 嵌套評論
- 判斷字符串是否是合法的 json 字符串
- 單元測試
- 計算出兩個日期的diff
- 自定義一個類文件讓composer加載
- 時間加減
- 對象數組互轉方法
- 用戶停留過久自動退出登錄
- optional 輔助方法
- 文件下載
- Api
- Dingo api
- auth.basic
- api_token
- Jwt-Auth
- passport
- Auth
- Authentication 和 Authorization
- Auth Facade
- 授權策略
- Gates
- composer包
- debug包
- idehelp包
- image處理
- 驗證碼
- jq插件
- 第三方登錄
- 第三方支付
- log顯示包
- 微信包
- xss過濾
- Excel包
- MongoDB
- php操作
- 聚合查詢
- 發送帶附件郵件
- 中文轉拼音包
- clockwork網頁調試
- emoji表情
- symfony組件
- swooletw/laravel-swoole
- 常見問題
- 跨域問題
- Laravel隊列優先級的一個坑
- cache:clear清除緩存問題
- .env無法讀取
- 源碼相關基礎知識
- __set和__get
- 依賴注入、控制反轉和依賴倒置原則
- 控制反轉容器(Ioc Container)
- 深入服務容器
- call_user_func
- compact
- 中間件簡易實現
- array_reduce
- 中間件實現代碼
- Pipeline管道操作
- composer自動加載
- redis延時隊列
- 了解laravel redis隊列
- cli
- 源碼解讀
- Facade分析
- Facade源碼分析
- IOC服務容器
- 中間件原理
- 依賴注入淺析
- 微信
- 微信公眾號
- 常用接收消息
- 6大接收接口
- 常用被動回復消息
- 接口調用憑證
- 自定義菜單
- 新增素材
- 客服消息
- 二維碼
- 微信語音
- LBS定位
- 網頁授權
- JSSDK
- easywechat
- 小程序
- 小程序配置app.json