Node.js課程知識(shí)講解大全(四)

4.3.2 中間件的原理

中間件就是一個(gè)函數(shù)抡秆,它能夠訪問請(qǐng)求對(duì)象?(req)徒坡、響應(yīng)對(duì)象?(res) 以及應(yīng)用程序的請(qǐng)求/響應(yīng)循環(huán)中的下一個(gè)中間件函數(shù)潮秘。下一個(gè)中間件函數(shù)通常由名為 next 的變量來(lái)表示澄者。

中間件中可以執(zhí)行任意代碼抚笔,但主要執(zhí)行以下任務(wù):

對(duì)請(qǐng)求和響應(yīng)對(duì)象進(jìn)行更改扶认。

結(jié)束請(qǐng)求/響應(yīng)循環(huán)。

調(diào)用堆棧中的下一個(gè)中間件函數(shù)殊橙。

如果當(dāng)前中間件函數(shù)沒有結(jié)束請(qǐng)求/響應(yīng)循環(huán)辐宾,那么它必須調(diào)用 next()狱从,以將控制權(quán)傳遞給下一個(gè)中間件函數(shù)。否則叠纹,請(qǐng)求將保持掛起狀態(tài)季研。

4.3.3 中間件的使用方法

使用 app.use() 和 app.[METHOD]() 函數(shù)將應(yīng)用層中間件綁定到應(yīng)用程序?qū)ο?/a>的實(shí)例,其中 METHOD 是中間件函數(shù)處理的請(qǐng)求的小寫 HTTP 方法(例如 get誉察、put 或 post)与涡。

var app = express();

app.use(function (req, res, next) {

? console.log('Time:', Date.now());

? next();

});

// 在 /user/:id 路徑中為任何類型的 HTTP 請(qǐng)求執(zhí)行此中間件函數(shù)

// 中間件可以傳遞多個(gè),用于順序調(diào)用持偏。

app.use('/user/:id', function (req, res, next) {

? console.log('Request Type:', req.method);

? next();

}, function (req, res, next) {

? console.log('Request Type:', req.method);

? next();

});

// 在/user/:id 路徑中為 GET 請(qǐng)求執(zhí)行此中間件函數(shù)

app.get('/user/:id', function (req, res, next) {

? res.send('USER');

? //此時(shí)請(qǐng)求已經(jīng)完成

});

// 要跳過路由器中間件堆棧中剩余的中間件函數(shù)驼卖,請(qǐng)調(diào)用 next('route') 將控制權(quán)傳遞給下一個(gè)路由。

// 注:next('route') 僅在使用 app.METHOD() 或 router.METHOD() 函數(shù)裝入的中間件函數(shù)中有效鸿秆。

app.get('/user/:id', function (req, res, next) {

? // if the user ID is 0, skip to the next route

? if (req.params.id == 0) next('route');

? // otherwise pass the control to the next middleware function in this stack

? else next(); //

}, function (req, res, next) {

? // render a regular page

? res.render('regular');

});

// if the user ID is 0,this route will execute.

app.get('/user/:id', function (req, res, next) {

? res.render('special');

});

注意點(diǎn):

Express 使用?path-to-regexp?來(lái)匹配路由路徑酌畜。匹配規(guī)則:

/abc/:id:匹配/abc/1,/abc/xf卿叽,/abc/桥胞,其中:id表示任意參數(shù),但它必須是子路徑考婴。

/abc?d:匹配abcd或者abd贩虾,其中c?表示c可有可無(wú)。

/ab+cd:匹配abcd沥阱,abbbcd缎罢,其中b+表示可以任意一個(gè)或多個(gè)。

/ab\*cd:匹配abcd喳钟,abicd屁使,其中\(zhòng) *表示任意值。

path中也可以存放數(shù)組奔则,表示匹配每一項(xiàng)蛮寂。

app.all():用于為express或者路由增加中間件,"/"會(huì)匹配多種地址或者子地址易茬。

app.all():用于匹配express或者路由任意請(qǐng)求酬蹋,"/"只會(huì)匹配精確地址。

res.send():電風(fēng)扇

會(huì)自動(dòng)為內(nèi)容設(shè)置Content-Type,如果傳遞文本抽莱,則設(shè)置text/html范抓。

res.send() 只能調(diào)用一次,調(diào)用完畢會(huì)自動(dòng)調(diào)用res.end()食铐,如果想多次輸出匕垫,可以使用res.write。

4.3.4 常用中間件

1. 路由器層中間件

路由器層中間件的工作方式與應(yīng)用層中間件基本相同虐呻。

// index.js

const express = require('express')

const router = require('./router')

const app = express()

app.use(router)

app.listen(3000, () => {

? ? console.log('服務(wù)器創(chuàng)建完畢,監(jiān)聽3000端口')

})

//router.js

const express = require('express')

const router = express.Router()

router.all('/', (req, res, next) => {

? ? res.send('你壞')

? ? next()

})

router.all('/user/:id', (req, res, next) => {

? ? if (req.params.id == 0) {

? ? ? ? next('route')

? ? } else if (req.params.id == 1) {

? ? ? ? res.send('我是老大')

? ? } else {

? ? ? ? res.set({

? ? ? ? ? ? 'Content-Type': 'text/html',

? ? ? ? })

? ? ? ? res.write('我是明明')

? ? ? ? res.write('abcd')

? ? ? ? res.end()

? ? ? ? next()

? ? }

}, (req, res, next) => {

? ? console.log('下一個(gè)中間件')

})

router.use('/user/:id', (req, res, next) => {

? ? res.send('超級(jí)管理員')

})

module.exports = router

2. body和querystring的轉(zhuǎn)換

req中接收到的body默認(rèn)是一個(gè)字符串象泵,我們?cè)谝话銉A向于把它轉(zhuǎn)換成一個(gè)json對(duì)象來(lái)使用寞秃。

使用第三方中間件body-parser可以為req做轉(zhuǎn)換,bodyParser除了可以將body轉(zhuǎn)換成json外偶惠,還可以轉(zhuǎn)換成其他格式春寿。

bodyParser.json():只有請(qǐng)求的Header的Content-Type包含text/json,并且body確實(shí)是json數(shù)據(jù)才會(huì)轉(zhuǎn)換成功忽孽,否則得到的req.body是空對(duì)象绑改。

const express = require('express')

const bodyParser = require('body-parser')

const router = express.Router()

router.all('/body-parser/true', bodyParser.json(), (req, res) => {

? ? res.send(req.body)

})

router.all('/body-parser/false', (req, res) => {

? ? res.send(req.body)

})

module.exports = router

express 4.x默認(rèn)的req.query就是一個(gè)對(duì)象,因此不需要對(duì)查詢字符串進(jìn)行轉(zhuǎn)換兄一。

3. 靜態(tài)資源中間件

express提供了express.static()作為靜態(tài)資源中間件使用厘线,只需要傳遞一個(gè)靜態(tài)資源路徑即可。

在項(xiàng)目目錄中加入一個(gè)public文件夾出革,放入一個(gè)nodejs.jpg文件皆的。

編寫如下代碼。

app.use(express.static(path.resolve(__dirname, './public')))

在瀏覽器直接輸入網(wǎng)站根路徑+文件名即可訪問文件蹋盆。

4.4 Express 腳手架

使用express-generator可以快速搭建一個(gè)Express項(xiàng)目,并能自動(dòng)下載依賴硝全,可以省去很多步驟栖雾。

使用npx一鍵安裝

npx express-generator --ejs <項(xiàng)目名稱>

npx命令

npx是npm從5.2版開始增加了的命令,主要用于快速調(diào)用node_modules/.bin/ 的命令伟众,如:

以前:$ node-modules/.bin/mocha --version

現(xiàn)在:$ npx mocha --version

同時(shí)還能避免全局安裝模塊而直接使用這種全局模塊析藕,如:create-react-app模塊

以前:

1.先安裝:npm install -g create-react-app;

2.在使用:create-react-app 工程名凳厢;

現(xiàn)在一步搞定:

npx create-react-app 工程名

express-generator 支持的可選參數(shù)

Options:

? ? -h, --help? ? ? ? ? 輸出使用方法

? ? ? ? --version? ? ? 輸出版本號(hào)

? ? -e, --ejs? ? ? ? ? 添加對(duì) ejs 模板引擎的支持

? ? ? ? --hbs? ? ? ? ? 添加對(duì) handlebars 模板引擎的支持

? ? ? ? --pug? ? ? ? ? 添加對(duì) pug 模板引擎的支持

? ? -H, --hogan? ? ? ? 添加對(duì) hogan.js 模板引擎的支持

? ? ? ? --no-view? ? ? 創(chuàng)建不帶視圖引擎的項(xiàng)目

? ? -v, --view <engine> 添加對(duì)視圖引擎(view) <engine> 的支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默認(rèn)是 jade 模板引擎)

? ? -c, --css <engine>? 添加樣式表引擎 <engine> 的支持 (less|stylus|compass|sass) (默認(rèn)是普通的 css 文件)

? ? ? ? --git? ? ? ? ? 添加 .gitignore

? ? -f, --force? ? ? ? 強(qiáng)制在非空目錄下創(chuàng)建

模板引擎

Express模板引擎(Template Engine), 是用來(lái)解析對(duì)應(yīng)類型模板文件然后動(dòng)態(tài)生成由數(shù)據(jù)和靜態(tài)頁(yè)面組成的HTML的一個(gè)工具账胧,也就是可以編譯成HTML文件的一種預(yù)編譯文件。

Express中最常用的兩個(gè)模板工具是ejs和jade(已經(jīng)改名為pug先紫,不過習(xí)慣上還是叫jade)治泥,ejs是非常接近html語(yǔ)法的模板,而jade模板是非常簡(jiǎn)潔的語(yǔ)法遮精,和HTML語(yǔ)法差異較大居夹,jade模板在這里可以學(xué)習(xí)

簡(jiǎn)要學(xué)習(xí)ejs模板語(yǔ)法:官方文檔

<!DOCTYPE html>

<html>

<head>

? <title><%= title %></title>

? <link rel='stylesheet' href='/stylesheets/style.css' />

</head>

<body>

? <%# 渲染變量 %>

? <h1><%= title %></h1>

? <p>Welcome to <%= title %></p>

? <% var a = 10, b = 11; %>

? <% if(a > b){ %>

? <div>ddddd</div>

? <% } %>

? <ul>

? ? <%# 只執(zhí)行代碼,不渲染內(nèi)容 %>

? ? <% users.forEach(function(user){ %>

? ? <%# 渲染變量 %>

? ? <li><%= user.name %></li>

? ? <% }) %>

? </ul>

</body>

</html>

? 標(biāo)簽含義:

? ```markdown

? `<%` '腳本' 標(biāo)簽本冲,用于流程控制准脂,無(wú)輸出。

? `<%_` 刪除其前面的空格符

? `<%=` 輸出數(shù)據(jù)到模板(輸出是轉(zhuǎn)義 HTML 標(biāo)簽)

? `<%-` 輸出非轉(zhuǎn)義的數(shù)據(jù)到模板

? `<%#` 注釋標(biāo)簽檬洞,不執(zhí)行狸膏、不輸出內(nèi)容

? `<%%` 輸出字符串 '<%'

`%>` 一般結(jié)束標(biāo)簽

? `-%>` 刪除緊隨其后的換行符

`_%>` 將結(jié)束標(biāo)簽后面的空格符刪除

? 模板引擎和索取模板的目錄,需要通過以下代碼指定:

? app.set('views', path.join(__dirname, 'views'));

app.set('view engine', 'ejs');

? 模板是在路由中通過res.render渲染并輸出的:

? router.get('/', function (req, res, next) {

? ? res.render('index', { title: 'Express', users: [{ name: '花花' }, { name: '世界' }] });

? });

五. 使用MongoDB數(shù)據(jù)庫(kù)

到目前為止添怔,我們開發(fā)的API接口都是生成的假數(shù)據(jù)湾戳。如果有這樣一個(gè)系統(tǒng)贤旷,需要使用Express+Bootstrap開發(fā)一套用戶的管理系統(tǒng),所有用戶的數(shù)據(jù)通過上傳來(lái)提供院塞,并且需要把數(shù)據(jù)保存遮晚。那么這種情形下,數(shù)據(jù)庫(kù)就成了必不可少的工具拦止。

5.1 什么是數(shù)據(jù)庫(kù)

數(shù)據(jù)庫(kù)指的是以一定方式儲(chǔ)存在一起县遣、能為多個(gè)用戶共享、具有盡可能小的冗余度汹族、與應(yīng)用程序彼此獨(dú)立的數(shù)據(jù)集合萧求,用戶可以對(duì)文件中的數(shù)據(jù)運(yùn)行新增、截取顶瞒、更新夸政、刪除等操作。

數(shù)據(jù)庫(kù)軟件應(yīng)稱為DBMS(數(shù)據(jù)庫(kù)管理系統(tǒng))榴徐。數(shù)據(jù)庫(kù)是通過 DBMS 創(chuàng)建和操縱的容器守问。數(shù)據(jù)庫(kù)可以是保存在硬件設(shè)備上的文件,但也可以不是坑资。在很大程度上說(shuō)耗帕,數(shù)據(jù)庫(kù)究竟是文件還是別的什么東西并不重要,因?yàn)槟悴⒉恢苯釉L問數(shù)據(jù)庫(kù)袱贮;你使用的是DBMS仿便,它替你訪問數(shù)據(jù)庫(kù)。

5.2 數(shù)據(jù)庫(kù)的分類

按照邏輯劃分攒巍,數(shù)據(jù)庫(kù)分為關(guān)系型和非關(guān)系型數(shù)據(jù)庫(kù)嗽仪。

關(guān)系型數(shù)據(jù)庫(kù)

關(guān)系型數(shù)據(jù)庫(kù)是創(chuàng)建在關(guān)系模型基礎(chǔ)上的數(shù)據(jù)庫(kù),它是數(shù)據(jù)存儲(chǔ)的傳統(tǒng)標(biāo)準(zhǔn)柒莉。標(biāo)準(zhǔn)數(shù)據(jù)查詢語(yǔ)言SQL就是一種基于關(guān)系數(shù)據(jù)庫(kù)的語(yǔ)言闻坚,這種語(yǔ)言執(zhí)行對(duì)關(guān)系數(shù)據(jù)庫(kù)中數(shù)據(jù)的檢索和操作。

關(guān)系數(shù)據(jù)庫(kù)使用表存儲(chǔ)數(shù)據(jù)常柄,在使用之前需要定義數(shù)據(jù)結(jié)構(gòu)鲤氢,而且具有數(shù)據(jù)完整性約束。

SQL是精確的西潘。它最適合于具有精確標(biāo)準(zhǔn)的定義明確的項(xiàng)目卷玉。典型的使用場(chǎng)景是在線商店和銀行系統(tǒng)。

常用的關(guān)系數(shù)據(jù)庫(kù):

MySQL

PostgreSQL

SQL Server

Oracle

非關(guān)系型數(shù)據(jù)庫(kù)(NoSQL)

非關(guān)系型數(shù)據(jù)庫(kù)是基于鍵值對(duì)的喷市,可以想象成表中的主鍵和值的對(duì)應(yīng)關(guān)系相种,而且不需要經(jīng)過SQL層的解析,所以性能非常高,而且易于擴(kuò)展寝并。

菲關(guān)系型數(shù)據(jù)庫(kù)使用類JSON的文檔存儲(chǔ)數(shù)據(jù)箫措,格式不限定,不會(huì)對(duì)數(shù)據(jù)進(jìn)行嚴(yán)格驗(yàn)證衬潦。

NoSQL是多變的斤蔓。它最適合于具有不確定需求的數(shù)據(jù)。典型的使用場(chǎng)景是社交網(wǎng)絡(luò)镀岛,客戶管理和網(wǎng)絡(luò)分析系統(tǒng)弦牡。

Redis

MongoDB

關(guān)系型和非關(guān)系型數(shù)據(jù)庫(kù)無(wú)分誰(shuí)優(yōu)誰(shuí)劣,他們有各自應(yīng)用的場(chǎng)景漂羊,而且很多情況還會(huì)結(jié)合使用驾锰。

5.3 MongoDB數(shù)據(jù)庫(kù)

MongoDB 是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù)。由 C++ 語(yǔ)言編寫走越。旨在為 WEB 應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案椭豫。

MongoDB并非純粹的非關(guān)系型數(shù)據(jù)庫(kù), 是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品旨指,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富赏酥,最像關(guān)系數(shù)據(jù)庫(kù)的。MongoDB 將數(shù)據(jù)存儲(chǔ)為一個(gè)文檔谆构,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對(duì)組成今缚。MongoDB 文檔類似于 JSON 對(duì)象。字段值可以包含其他文檔低淡,數(shù)組及文檔數(shù)組。

因?yàn)镸ongoDB是基于JSON的查詢和存儲(chǔ)瞬项,它最接近JavaScript蔗蹋,而且性能很好,因此我們選用他來(lái)作為Express的數(shù)據(jù)庫(kù)使用囱淋。

5.3.1 安裝MongoDB

Windows猪杭、Mac安裝官網(wǎng)https://www.mongodb.com/download-center/enterprise

數(shù)據(jù)庫(kù)安裝過程記得選擇順帶安裝TLS/SSL工具。

5.3.2 準(zhǔn)備工作

安裝完畢后妥衣,我們需要?jiǎng)?chuàng)建一個(gè)用來(lái)存儲(chǔ)數(shù)據(jù)的目錄皂吮。

windows用戶需要手動(dòng)在C:\盤目錄創(chuàng)建一個(gè)data目錄,然后data內(nèi)部創(chuàng)建一個(gè)db目錄税手。

Mac用戶需要在root根目錄下創(chuàng)建一個(gè)data目錄蜂筹,然后data內(nèi)部創(chuàng)建一個(gè)db目錄。

啟動(dòng)數(shù)據(jù)庫(kù):

mongod

啟動(dòng)成功后芦倒,保留這個(gè)終端窗口艺挪,開啟一個(gè)新的窗口,輸入mongo進(jìn)入mongo shell模式兵扬。

mongo

Windows用戶如果無(wú)法使用命令麻裳,需要設(shè)置環(huán)境變量指向MongoDB安裝目錄的bin目錄口蝠。

5.3.3 MongoDB中的概念

MongoDB是非關(guān)系型數(shù)據(jù)庫(kù),它其中有些術(shù)語(yǔ)相對(duì)于關(guān)系型數(shù)據(jù)庫(kù)是不一樣的津坑。

MongoDB術(shù)語(yǔ)對(duì)應(yīng)的SQL術(shù)語(yǔ)解釋/說(shuō)明

databasedatabase數(shù)據(jù)庫(kù)

collectiontable數(shù)據(jù)庫(kù)表/集合

documentrow數(shù)據(jù)記錄行/文檔

fieldcolumn數(shù)據(jù)字段/域

indexindex索引

table joins表連接,MongoDB不支持

primary keyprimary key主鍵,MongoDB自動(dòng)將_id字段設(shè)置為主鍵

數(shù)據(jù)庫(kù)(Database)

一個(gè)mongodb中可以建立多個(gè)數(shù)據(jù)庫(kù)妙蔗。

MongoDB的默認(rèn)數(shù)據(jù)庫(kù)為"db",該數(shù)據(jù)庫(kù)存儲(chǔ)在data目錄中疆瑰。

MongoDB的單個(gè)實(shí)例可以容納多個(gè)獨(dú)立的數(shù)據(jù)庫(kù)眉反,每一個(gè)都有自己的集合和權(quán)限,不同的數(shù)據(jù)庫(kù)也放置在不同的文件中乃摹。

show dbs 命令可以顯示所有數(shù)據(jù)的列表禁漓。

> show dbs

執(zhí)行db命令可以顯示當(dāng)前數(shù)據(jù)庫(kù)對(duì)象或集合。

> db

運(yùn)行use命令孵睬,可以連接到一個(gè)指定的數(shù)據(jù)庫(kù)播歼。

> use local

文檔(Document)

文檔是一組鍵值(key-value)對(duì)。MongoDB 的文檔內(nèi)部的字段和數(shù)據(jù)類型并不是強(qiáng)制性的掰读,這與關(guān)系型數(shù)據(jù)庫(kù)有很大的區(qū)別秘狞,也是 MongoDB 非常突出的特點(diǎn)。

需要注意的是:

文檔中的鍵/值對(duì)是有序的蹈集。

文檔中的值不僅可以是在雙引號(hào)里面的字符串烁试,還可以是其他幾種數(shù)據(jù)類型(甚至可以是整個(gè)嵌入的文檔)。

MongoDB區(qū)分類型和大小寫拢肆。

MongoDB的文檔不能有重復(fù)的鍵减响。

db.col.findOne()

集合(collection)

多個(gè)文檔可以構(gòu)成一個(gè)集合。

集合支持capped特性郭怪,該特性會(huì)創(chuàng)建一個(gè)固定大小的集合支示,這樣collection 的數(shù)據(jù)存儲(chǔ)空間值是提前分配的。

db.createCollection("mycoll", {capped:true, size:100000})

數(shù)據(jù)類型

ObjectId

MongoDB支持很多種數(shù)據(jù)類型鄙才,但有一種類型很重要也很特殊颂鸿,就是ObjectId類型。

ObjectId 類似主鍵攒庵,可以很快的去生成和排序嘴纺,它由12 bytes組成。

MongoDB 中存儲(chǔ)的文檔必須有一個(gè) _id 鍵浓冒,這個(gè)鍵的值默認(rèn)是個(gè) ObjectId 對(duì)象栽渴。

由于 ObjectId 中保存了創(chuàng)建的時(shí)間戳,所以你不需要為你的文檔保存時(shí)間戳字段稳懒,你可以通過getTimestamp 函數(shù)來(lái)獲取文檔的創(chuàng)建時(shí)間:

objectId.getTimestamp()

字符串

字符串默認(rèn)UTF-8編碼熔萧。

日期

表示當(dāng)前距離 1970年1月1日 的毫秒數(shù)。日期類型是有符號(hào)的, 負(fù)數(shù)表示 1970 年之前的日期。

5.3.4 shell操作數(shù)據(jù)庫(kù)

MongoDB 中默認(rèn)的數(shù)據(jù)庫(kù)為 test佛致,如果你沒有創(chuàng)建新的數(shù)據(jù)庫(kù)贮缕,集合將存放在 test 數(shù)據(jù)庫(kù)中。

創(chuàng)建數(shù)據(jù)庫(kù)

> use runoob

switched to db runoob

> db

runoob

>

查看數(shù)據(jù)庫(kù)

> show dbs

admin? 0.000GB

config? 0.000GB

local? 0.000GB

>

剛剛創(chuàng)建的數(shù)據(jù)庫(kù)沒有展示出來(lái)俺榆,因?yàn)樗€沒有添加數(shù)據(jù)感昼。

> db.runoob.insert({"name":"菜鳥教程"})

WriteResult({ "nInserted" : 1 })

> show dbs

admin? 0.000GB

config? 0.000GB

local? 0.000GB

runoob? 0.000GB

刪除數(shù)據(jù)庫(kù)

> use runoob

switched to db runoob

> db.dropDatabase()

{ "dropped" : "runoob", "ok" : 1 }

創(chuàng)建集合

> db.createCollection("users")

{ "ok" : 1 }

>

查看集合

> show collections

users

system.indexes

刪除集合

> db.users.drop()

集合中插入文檔

>db.users.insert({"name":"小明"})

集合中更新文檔

更新的命令比較復(fù)雜:

db.collection.update(

? <query>,

? <update>,

? {

? ? upsert: <boolean>,

? ? multi: <boolean>,

? ? writeConcern: <document>

? }

)

參數(shù)說(shuō)明:

query?: update的查詢條件,類似sql update查詢內(nèi)where后面的罐脊。

update?: update的對(duì)象和一些更新的操作符(如$,$inc...)等定嗓,也可以理解為sql update查詢內(nèi)set后面的

upsert?: 可選,這個(gè)參數(shù)的意思是萍桌,如果不存在update的記錄宵溅,是否插入objNew,true為插入,默認(rèn)是false上炎,不插入恃逻。

multi?: 可選,mongodb 默認(rèn)是false,只更新找到的第一條記錄藕施,如果這個(gè)參數(shù)為true,就把按條件查出來(lái)多條記錄全部更新寇损。

writeConcern?:可選,拋出異常的級(jí)別裳食。

> db.users.update({'name':'小明'},{$set:{'name':'小花'}})

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })? # 輸出信息

刪除文檔

db.collection.remove(

? <query>,

? {

? ? justOne: <boolean>,

? ? writeConcern: <document>

? }

)

參數(shù)說(shuō)明:

query?:(可選)刪除的文檔的條件矛市。

justOne?: (可選)如果設(shè)為 true 或 1,則只刪除一個(gè)文檔诲祸,如果不設(shè)置該參數(shù)浊吏,或使用默認(rèn)值 false,則刪除所有匹配條件的文檔救氯。

writeConcern?:(可選)拋出異常的級(jí)別卿捎。

> db.col.remove({'title':'MongoDB 教程'})

WriteResult({ "nRemoved" : 2 })

查詢文檔

db.collection.find(query, projection)

query?:可選,使用查詢操作符指定查詢條件

projection?:可選径密,使用投影操作符指定返回的鍵。查詢時(shí)返回文檔中所有鍵值躺孝, 只需省略該參數(shù)即可(默認(rèn)省略)享扔。

> db.col.find().pretty()

{

? ? ? ? "_id" : ObjectId("56063f17ade2f21f36b03133"),

? ? ? ? "title" : "MongoDB 教程",

? ? ? ? "description" : "MongoDB 是一個(gè) Nosql 數(shù)據(jù)庫(kù)",

? ? ? ? "by" : "菜鳥教程",

? ? ? ? "url" : "http://www.runoob.com",

? ? ? ? "tags" : [

? ? ? ? ? ? ? ? "mongodb",

? ? ? ? ? ? ? ? "database",

? ? ? ? ? ? ? ? "NoSQL"

? ? ? ? ],

? ? ? ? "likes" : 100

}

此外findOne可以只查詢一個(gè)

上面的查詢是 基于AND條件,也可以基于OR條件查詢

>db.col.find({$or:[{"by":"菜鳥教程"},{"title": "MongoDB 教程"}]}).pretty()

{

? ? ? ? "_id" : ObjectId("56063f17ade2f21f36b03133"),

? ? ? ? "title" : "MongoDB 教程",

? ? ? ? "description" : "MongoDB 是一個(gè) Nosql 數(shù)據(jù)庫(kù)",

? ? ? ? "by" : "菜鳥教程",

? ? ? ? "url" : "http://www.runoob.com",

? ? ? ? "tags" : [

? ? ? ? ? ? ? ? "mongodb",

? ? ? ? ? ? ? ? "database",

? ? ? ? ? ? ? ? "NoSQL"

? ? ? ? ],

? ? ? ? "likes" : 100

}

>

此外還可以基于大于植袍、小于的查詢

> db.col.find({"by":"小明", "likes": {$gt:50}, $or: [{"by": "菜鳥教程"},{"title": "MongoDB 教程"}]}).pretty()

{

? ? ? ? "_id" : ObjectId("56063f17ade2f21f36b03133"),

? ? ? ? "title" : "MongoDB 教程",

? ? ? ? "description" : "MongoDB 是一個(gè) Nosql 數(shù)據(jù)庫(kù)",

? ? ? ? "by" : "菜鳥教程",

? ? ? ? "url" : "http://www.runoob.com",

? ? ? ? "tags" : [

? ? ? ? ? ? ? ? "mongodb",

? ? ? ? ? ? ? ? "database",

? ? ? ? ? ? ? ? "NoSQL"

? ? ? ? ],

? ? ? ? "likes" : 100

}

操作格式范例RDBMS中的類似語(yǔ)句

等于{:}db.col.find({"by":"菜鳥教程"}).pretty()where by = '菜鳥教程'

小于{:{$lt:}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50

小于或等于{:{$lte:}}db.col.find({"likes":{$lte:50}}).pretty()where likes <= 50

大于{:{$gt:}}db.col.find({"likes":{$gt:50}}).pretty()where likes > 50

大于或等于{:{$gte:}}db.col.find({"likes":{$gte:50}}).pretty()where likes >= 50

不等于{:{$ne:}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50

limit方法

如果你需要在MongoDB中讀取指定數(shù)量的數(shù)據(jù)記錄惧眠,可以使用MongoDB的Limit方法,limit()方法接受一個(gè)數(shù)字參數(shù)于个,該參數(shù)指定從MongoDB中讀取的記錄條數(shù)氛魁。

> db.col.find({},{"title":1,_id:0}).limit(2)

{ "title" : "PHP 教程" }

{ "title" : "Java 教程" }

我們除了可以使用limit()方法來(lái)讀取指定數(shù)量的數(shù)據(jù)外,還可以使用skip()方法來(lái)跳過指定數(shù)量的數(shù)據(jù),skip方法同樣接受一個(gè)數(shù)字參數(shù)作為跳過的記錄條數(shù)秀存。

以下實(shí)例只會(huì)顯示第二條文檔數(shù)據(jù)

>db.col.find({},{"title":1,_id:0}).limit(1).skip(1)

{ "title" : "Java 教程" }

>

排序

在 MongoDB 中使用 sort() 方法對(duì)數(shù)據(jù)進(jìn)行排序捶码,sort() 方法可以通過參數(shù)指定排序的字段,并使用 1 和 -1 來(lái)指定排序的方式或链,其中 1 為升序排列惫恼,而 -1 是用于降序排列。

>db.col.find({},{"title":1,_id:0}).sort({"likes":-1})

{ "title" : "PHP 教程" }

{ "title" : "Java 教程" }

{ "title" : "MongoDB 教程" }

>

索引

索引通常能夠極大的提高查詢的效率澳盐,如果沒有索引祈纯,MongoDB在讀取數(shù)據(jù)時(shí)必須掃描集合中的每個(gè)文件并選取那些符合查詢條件的記錄。這種掃描全集合的查詢效率是非常低的叼耙,特別在處理大量的數(shù)據(jù)時(shí)腕窥,查詢可以要花費(fèi)幾十秒甚至幾分鐘,這對(duì)網(wǎng)站的性能是非常致命的筛婉。

為col集合建立索引簇爆,基于title

>db.col.createIndex({"title":1})

>

聚合

MongoDB中聚合(aggregate)主要用于處理數(shù)據(jù)(諸如統(tǒng)計(jì)平均值,求和等),并返回計(jì)算后的數(shù)據(jù)結(jié)果倾贰。

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])

{

? "result" : [

? ? ? {

? ? ? ? "_id" : "runoob.com",

? ? ? ? "num_tutorial" : 2

? ? ? },

? ? ? {

? ? ? ? "_id" : "Neo4j",

? ? ? ? "num_tutorial" : 1

? ? ? }

? ],

? "ok" : 1

}

>

表達(dá)式描述實(shí)例

$sum計(jì)算總和冕碟。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])

$avg計(jì)算平均值db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])

$min獲取集合中所有文檔對(duì)應(yīng)值得最小值。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])

$max獲取集合中所有文檔對(duì)應(yīng)值得最大值匆浙。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])

$push在結(jié)果文檔中插入值到一個(gè)數(shù)組中安寺。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])

$addToSet在結(jié)果文檔中插入值到一個(gè)數(shù)組中,但不創(chuàng)建副本首尼。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])

$first根據(jù)資源文檔的排序獲取第一個(gè)文檔數(shù)據(jù)挑庶。db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])

$last根據(jù)資源文檔的排序獲取最后一個(gè)文檔數(shù)據(jù)db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

以上就是MongoDB的基本使用方式,我們?cè)诼?lián)系過程中發(fā)現(xiàn)软能,mongoDB的shell非常難用迎捺,在這里推薦使用GUI工具來(lái)管理數(shù)據(jù)庫(kù):Robo3T來(lái)管理數(shù)據(jù)庫(kù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末查排,一起剝皮案震驚了整個(gè)濱河市凳枝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跋核,老刑警劉巖岖瑰,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異砂代,居然都是意外死亡蹋订,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門刻伊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)露戒,“玉大人椒功,你說(shuō)我怎么就攤上這事≈鞘玻” “怎么了动漾?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)撩鹿。 經(jīng)常有香客問我谦炬,道長(zhǎng),這世上最難降的妖魔是什么节沦? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任键思,我火速辦了婚禮,結(jié)果婚禮上甫贯,老公的妹妹穿的比我還像新娘吼鳞。我一直安慰自己,他們只是感情好叫搁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布赔桌。 她就那樣靜靜地躺著,像睡著了一般渴逻。 火紅的嫁衣襯著肌膚如雪疾党。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天惨奕,我揣著相機(jī)與錄音雪位,去河邊找鬼。 笑死梨撞,一個(gè)胖子當(dāng)著我的面吹牛雹洗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卧波,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼时肿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了港粱?” 一聲冷哼從身側(cè)響起螃成,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎查坪,沒想到半個(gè)月后寸宏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咪惠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淋淀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遥昧。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡覆醇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炭臭,到底是詐尸還是另有隱情永脓,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布鞋仍,位于F島的核電站常摧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏威创。R本人自食惡果不足惜落午,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肚豺。 院中可真熱鬧溃斋,春花似錦、人聲如沸吸申。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)截碴。三九已至残黑,卻和暖如春牵囤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工雏亚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枉圃。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓抽诉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親妒牙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子彼哼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容