Node + Express 后臺開發 —— 起步

Node + Express 后臺開發 —— 起步

前面陸續學習了一下 node、npm、模塊,也稍嘗試 Express,感覺得換一個思路加快進行。

比如筆者對前端的開發已較熟悉,如果領導給一個內部小網站的需求,難道說你得給我配置一個后端

又不是做一個復雜的后端,只是簡單的數據存儲(增刪改查)、上傳文件、下載csv或excel,無需考慮性能、穩定性、負載均衡等等,怎么就不能做

目標

實現簡單后臺的開發和部署

Express 項目生成器

生成項目

可通過應用生成器工具?express-generator?可以快速創建一個應用的骨架

創建項目文件夾 spug-back-end,進入項目后執行?npx express-generator:

Administrator@ /e/spug-back-end
$ npx express-generator
npm WARN exec The following package was not found and will be installed: express-generator@4.16.1
npm WARN deprecated mkdirp@0.5.1: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)warning: the default view engine will not be jade in future releaseswarning: use `--view=jade' or `--help' for additional optionscreate : public\create : public\javascripts\create : public\images\create : public\stylesheets\create : public\stylesheets\style.csscreate : routes\create : routes\index.jscreate : routes\users.jscreate : views\create : views\error.jadecreate : views\index.jadecreate : views\layout.jadecreate : app.jscreate : package.jsoncreate : bin\create : bin\wwwinstall dependencies:$ npm installrun the app:$ DEBUG=spug-back-end:* npm start

生成如下內容:

Administrator@ /e/spug-back-end
$ ll
total 5
-rw-r--r-- 1 Administrator 197121 1075 Apr 14 15:06 app.js
drwxr-xr-x 1 Administrator 197121    0 Apr 14 15:06 bin/
-rw-r--r-- 1 Administrator 197121  301 Apr 14 15:06 package.json
drwxr-xr-x 1 Administrator 197121    0 Apr 14 15:06 public/
drwxr-xr-x 1 Administrator 197121    0 Apr 14 15:06 routes/
drwxr-xr-x 1 Administrator 197121    0 Apr 14 15:06 views/

Tip: 對于較老的 Node 版本(8.2.0 以下),請通過 npm 將 Express 應用程序生成器安裝到全局環境中并使用

$ npm install -g express-generator
$ express

根據上文提示安裝依賴?npm install

Administrator@ /e/spug-back-end
$ npm install
npm WARN deprecated constantinople@3.0.2: Please update to at least constantinople 3.1.1
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jadeadded 99 packages, and audited 100 packages in 22s1 package is looking for fundingrun `npm fund` for details8 vulnerabilities (1 low, 4 high, 3 critical)To address all issues (including breaking changes), run:npm audit fix --forceRun `npm audit` for details.

全局安裝 nodemon(在Node.js應用程序開發過程中使用的簡單監視器腳本),編碼過程中無需重啟 node 服務即可生效:

PS E:\spug-back-end> npm i -g nodemonchanged 32 packages, and audited 33 packages in 1s3 packages are looking for fundingrun `npm fund` for detailsfound 0 vulnerabilities

修改啟動腳本:

   "version": "0.0.0","private": true,"scripts": {
-    "start": "node ./bin/www"
+    "start": "nodemon ./bin/www"

通過?npm run start?本地啟動服務:

PS E:\spug-back-end> npm run start> spug-back-end@0.0.0 start
> nodemon ./bin/www[nodemon] 2.0.22
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node ./bin/www`

入口文件?/bin/www.js?默認使用的是 3000 端口(var port = normalizePort(process.env.PORT || '3000');

瀏覽器訪問?http://localhost:3000/,頁面顯示:

Express
Welcome to Express

項目解讀

模板

views?目錄中存放的是 jade?模板文件:

Administrator@ /e/spug-back-end/views (master)
$ ls
error.jade  index.jade  layout.jade

首頁對應的模板是 index.jade:

Administrator@ /e/spug-back-end/views (master)
$ cat index.jade
extends layoutblock contenth1= titlep Welcome to #{title}

Express 生成器默認使用 jade 模板,對前端不是很友好,筆者通過?npx express-generator --view=ejs?選用?ejs模板(對前端更友好)重新創建。

首頁對應模板 index.ejs:

<!DOCTYPE html>
<html><head><title><%= title %></title><link rel='stylesheet' href='/stylesheets/style.css' /></head><body><h1><%= title %></h1><p>Welcome to <%= title %></p></body>
</html>
入口文件

bin/www.js?是應用的入口文件。

核心代碼如下:

// 加載 app.js
var app = require('../app');
var http = require('http');var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);// 創建 http server
var server = http.createServer(app);
server.listen(port);

完整代碼如下:

#!/usr/bin/env node/*** Module dependencies.*/var app = require('../app');
var debug = require('debug')('spug-back-end:server');
var http = require('http');/*** Get port from environment and store in Express.*/var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);/*** Create HTTP server.*/var server = http.createServer(app);/*** Listen on provided port, on all network interfaces.*/server.listen(port);
server.on('error', onError);
server.on('listening', onListening);/*** Normalize a port into a number, string, or false.*/function normalizePort(val) {var port = parseInt(val, 10);if (isNaN(port)) {// named pipereturn val;}if (port >= 0) {// port numberreturn port;}return false;
}/*** Event listener for HTTP server "error" event.*/function onError(error) {if (error.syscall !== 'listen') {throw error;}var bind = typeof port === 'string'? 'Pipe ' + port: 'Port ' + port;// handle specific listen errors with friendly messagesswitch (error.code) {case 'EACCES':console.error(bind + ' requires elevated privileges');process.exit(1);break;case 'EADDRINUSE':console.error(bind + ' is already in use');process.exit(1);break;default:throw error;}
}/*** Event listener for HTTP server "listening" event.*/function onListening() {var addr = server.address();var bind = typeof addr === 'string'? 'pipe ' + addr: 'port ' + addr.port;debug('Listening on ' + bind);
}

Tip: 和我們之前創建的最簡單的服務器類似

app.js

入口文件中引入 app.js,完整代碼如下:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
// Creates an Express application
var app = express();// view engine setup
// 模板引擎相關代碼
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');app.use(logger('dev'));
// for parsing application/json
app.use(express.json());
// for parsing application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// 放開靜態資源
app.use(express.static(path.join(__dirname, 'public')));// 定義兩個路由。一個返回頁面一個返回后端數據
// app.use([path,] callback [, callback...]) - 在指定路徑掛載指定的一個或多個中間件函數:當請求路徑的基匹配路徑時,執行中間件函數。
app.use('/', indexRouter);
app.use('/users', usersRouter);// catch 404 and forward to error handler
app.use(function(req, res, next) {next(createError(404));
});// error handler
app.use(function(err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

和我們之前用 Express 實現的報名系統?非常類似。這里創建了一個 Express 應用,并定義了兩個示例路由:

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');// 返回頁面
app.use('/', indexRouter);
// 返回后端數據
app.use('/users', usersRouter);
路由

app.js 使用了兩個路由。內容如下:

// routes/index.js
var express = require('express');
var router = express.Router();/* GET home page. */
router.get('/', function(req, res, next) {res.render('index', { title: 'Express' });
});module.exports = router;
// routes/users.js
var express = require('express');
var router = express.Router();/* GET users listing. */
router.get('/', function(req, res, next) {res.send('respond with a resource');
});module.exports = router;

瀏覽器訪問?http://localhost:3000/users,頁面顯示?respond with a resource

mongodb

數據庫通常會安裝到 linux 中,這里以 ubuntu 為例,通過?apt-get install mongodb?即可安裝,非常方便:

// 筆者剛已執行
root@linux:/home/pjl# apt-get install mongodb
Reading package lists... Done
Building dependency tree
Reading state information... Done
mongodb is already the newest version (1:3.6.9+really3.6.8+90~g8e540c0b6d-0ubuntu5.3).
0 upgraded, 0 newly installed, 0 to remove and 150 not upgraded.

數據庫現在已經啟動,我們通過mongo -version驗證安裝成功:

root@linux:/home/pjl# mongo -version
MongoDB shell version v3.6.8
git version: 8e540c0b6db93ce994cc548f000900bdc740f80a
OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
allocator: tcmalloc
modules: none
build environment:distarch: x86_64target_arch: x86_64

mongodb 配置文件是?/etc/mongodb.conf。請注意下面兩項配置:

// 遠程連接
#bind_ip = 127.0.0.1
bind_ip = 0.0.0.0// 開機自啟動
#auth = true
auth = true

MongoDB shell

輸入 mongo 即可進入?MongoDB shell(操作mongo):

root@linux:/home/pjl# mongo
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("aedc6541-4a67-4e60-8eb4-d1325c82d061") }
MongoDB server version: 3.6.8
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, seehttp://docs.mongodb.org/
Questions? Try the support grouphttp://groups.google.com/group/mongodb-user
Server has startup warnings:
2023-04-15T14:34:32.327+0800 I STORAGE  [initandlisten]
2023-04-15T14:34:32.327+0800 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2023-04-15T14:34:32.327+0800 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2023-04-15T14:34:34.861+0800 I CONTROL  [initandlisten]
2023-04-15T14:34:34.861+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2023-04-15T14:34:34.861+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2023-04-15T14:34:34.861+0800 I CONTROL  [initandlisten]
> helpdb.help()                    help on db methodsdb.mycoll.help()             help on collection methodssh.help()                    sharding helpersrs.help()                    replica set helpershelp admin                   administrative helphelp connect                 connecting to a db helphelp keys                    key shortcutshelp misc                    misc things to knowhelp mr                      mapreduceshow dbs                     show database namesshow collections             show collections in current databaseshow users                   show users in current databaseshow profile                 show most recent system.profile entries with time >= 1msshow logs                    show the accessible logger namesshow log [name]              prints out the last segment of log in memory, 'global' is defaultuse <db_name>                set current databasedb.foo.find()                list objects in collection foodb.foo.find( { a : 1 } )     list objects in foo where a == 1it                           result of the last line evaluated; use to further iterateDBQuery.shellBatchSize = x   set default number of items to display on shellexit                         quit the mongo shell
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

通過?help?可以查看幫助,通過show dbs?發現現在有三個數據庫。

新建數據庫

通過 use 可以創建或切換數據庫。比如:

// use - 創建數據庫 pjl_db。如果存在則直接切換
> use pjl_db
switched to db pjl_db
// db - 目前操作的是 pjl_db 數據庫
> db
pjl_db

由于新建的數據庫 pjl_db 什么都沒有,所以通過?show dbs?顯示不出來,可通過 createCollection 創建表,再次查詢即可顯示該數據庫。比如

// 新建數據庫未能展示
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
// 通過 tab 建有提示
> db.create
db.createCollection(  db.createRole(        db.createUser(        db.createView(
// 創建表 users。這里叫集合
> db.createCollection("users")
{ "ok" : 1 }
// 再次查詢則可顯示新建數據庫 pjl_db
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
pjl_db  0.000GB

Tipdb.createCollection("pjl_db", {size: 1024*1024, capped: true, max: 1000})?- 創建 pjl_db 數據庫,同時這個數據庫最多 1M,記錄數只能有1000條,在多一條則把第一條給替代。db.createCollection("users")?則不作限制。

刪除數據庫

通過 db.dropDatabase() 即可刪除數據庫。比如:

> db.dropDatabase()
{ "dropped" : "pjl_db", "ok" : 1 }
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

新增、查看和刪除表

通過?db.createCollection("users")?新建 users 表。比如:

// 創建表 users。這里叫集合
> db.createCollection("users")
{ "ok" : 1 }
// 再次查詢則可顯示新建數據庫 pjl_db
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
pjl_db  0.000GB
  • db.getCollectionNames - 查看有哪些表
  • db.tableName.drop - 刪除某張表

示例:

// 新建兩張表: table-b、table-c
> db.createCollection("table-b")
{ "ok" : 1 }
> db.createCollection("table-c")
{ "ok" : 1 }
// tab 提示
> db.getCollection
db.getCollection(       db.getCollectionInfos(  db.getCollectionNames(
// 有哪些表
> db.getCollectionNames()
[ "table-b", "table-c", "users" ]
// 刪除table-b表失敗
> db.table-b.drop()
2023-04-15T15:17:10.232+0800 E QUERY    [thread1] ReferenceError: b is not defined :
@(shell):1:1
// 刪除table-b表成功
> db["table-b"].drop()
true
> db.getCollectionNames()
[ "table-c", "users" ]

表格-新增數據

通過?db.users.save?可以向 users 表中單條、批量插入數據。甚至字段名不同,字段數量不同也能插入。請看示例:

// 給 users 表插入一條數據 {"name": 'pjl', age: 18}
> db.users.save({"name": 'pjl', age: 18})
WriteResult({ "nInserted" : 1 })
// 查詢users表
> db.users.find()
{ "_id" : ObjectId("643a513d73f16a13ae248f42"), "name" : "pjl", "age" : 18 }
// 批量插入數據
> db.users.save([{"name": 'pjl2', age: 19}, {"name": 'pjl3', age: 20}])
BulkWriteResult({"writeErrors" : [ ],"writeConcernErrors" : [ ],"nInserted" : 2,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})
// 批量插入成功
> db.users.find()
{ "_id" : ObjectId("643a513d73f16a13ae248f42"), "name" : "pjl", "age" : 18 }
{ "_id" : ObjectId("643a51db73f16a13ae248f44"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643a51db73f16a13ae248f45"), "name" : "pjl3", "age" : 20 }
// 換字段名和字段長度,也能插入成功
> db.users.save({"name2": 'pjl', age2: 18, tel: 131111111})
WriteResult({ "nInserted" : 1 })
> db.users.find()
{ "_id" : ObjectId("643a513d73f16a13ae248f42"), "name" : "pjl", "age" : 18 }
{ "_id" : ObjectId("643a51db73f16a13ae248f44"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643a51db73f16a13ae248f45"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643a529a73f16a13ae248f46"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }

Tip:向 mongo 表中插入數據非常自由,什么字段、什么類型都可以。

表格-刪除數據

通過?db.users.remove({age2:18})?可以刪除 age2=18 的數據,通過?db.users.remove({})?刪除 users 表中所有數據。請看示例:

// 目前有4條數據
> db.users.find()
{ "_id" : ObjectId("643a513d73f16a13ae248f42"), "name" : "pjl", "age" : 18 }
{ "_id" : ObjectId("643a51db73f16a13ae248f44"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643a51db73f16a13ae248f45"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643a529a73f16a13ae248f46"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }// 可以刪除 age2=18 的數據
> db.users.remove({age2:18})
WriteResult({ "nRemoved" : 1 })
> db.users.find()
{ "_id" : ObjectId("643a513d73f16a13ae248f42"), "name" : "pjl", "age" : 18 }
{ "_id" : ObjectId("643a51db73f16a13ae248f44"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643a51db73f16a13ae248f45"), "name" : "pjl3", "age" : 20 }// 刪除 users 表中所有數據是 `db.users.remove({})`。`db.users.remove()` 會報錯
> db.users.remove()
2023-04-16T09:10:55.859+0800 E QUERY    [thread1] Error: remove needs a query :
DBCollection.prototype._parseRemove@src/mongo/shell/collection.js:357:1
DBCollection.prototype.remove@src/mongo/shell/collection.js:382:18
@(shell):1:1
// 刪除 users 表中所有數據
> db.users.remove({})
WriteResult({ "nRemoved" : 3 })
> db.users.find()
>

表格-修改數據

通過?db.users.update({name:'pjl2'}, {$set: {age: 20}})?修改 name=pjl2 的數據,將 age 改為 20。

Tip:直接?db.users.update({name:'pjl'}, {age: 19})?會替換整條數據。

\$inc?指增加,如果需要減去,則將數字改成負數。

示例如下:

> db.users.find()
{ "_id" : ObjectId("643b4d0cd21fdd4d6f0b0484"), "name" : "pjl", "age" : 18 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0486"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0487"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643b4d1fd21fdd4d6f0b0488"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }
// 修改 name=pjl 的數據,將 age改為19
> db.users.update({name:'pjl'}, {age: 19})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
// 替換了條數據
> db.users.find()
{ "_id" : ObjectId("643b4d0cd21fdd4d6f0b0484"), "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0486"), "name" : "pjl2", "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0487"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643b4d1fd21fdd4d6f0b0488"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }
// 通過 $set 成功更改 age 而不影響其他字段
> db.users.update({name:'pjl2'}, {$set: {age: 20}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find()
{ "_id" : ObjectId("643b4d0cd21fdd4d6f0b0484"), "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0486"), "name" : "pjl2", "age" : 20 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0487"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643b4d1fd21fdd4d6f0b0488"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }
// 給 age 增加1
> db.users.update({name:'pjl2'}, {$inc: {age: 1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find()
{ "_id" : ObjectId("643b4d0cd21fdd4d6f0b0484"), "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0486"), "name" : "pjl2", "age" : 21 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0487"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643b4d1fd21fdd4d6f0b0488"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }
// 給 age 減去1
> db.users.update({name:'pjl2'}, {$inc: {age: -1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find()
{ "_id" : ObjectId("643b4d0cd21fdd4d6f0b0484"), "age" : 19 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0486"), "name" : "pjl2", "age" : 20 }
{ "_id" : ObjectId("643b4d17d21fdd4d6f0b0487"), "name" : "pjl3", "age" : 20 }
{ "_id" : ObjectId("643b4d1fd21fdd4d6f0b0488"), "name2" : "pjl", "age2" : 18, "tel" : 131111111 }

表格-查詢數據

首先清空 users 表,并插入6條數據。

find

通過?db.users.find()?查詢所有數據:

> db.users.find()
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li", "age" : 39, "tel" : "0730-1233" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia", "age" : 49, "tel" : "0730-1234" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
>
大于小于
  • $gt - 大于
  • $gte - 大于等于
  • $lt - 小于
  • $lte - 小于等于
// 查詢 age 大于 50 的數據
> db.users.find({age:{$gt: 50}})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
// 查詢 age 大于 69 的數據
> db.users.find({age:{$gt: 69}})
// 查詢 age 大于等于 69 的數據
> db.users.find({age:{$gte: 69}})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
// age 小于 20 
> db.users.find({age:{$lt: 20}})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
// 查詢 age 大于 10,小于 40 的數據
> db.users.find({age:{$gt:10, $lt:40}})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li", "age" : 39, "tel" : "0730-1233" }
>
單條件
  • db.users.find({name: "jia"})?- 查詢 name?等于?jia 的數據
  • db.users.find({name: /jia/})?- 查詢 name 中包含?jia 的數據
  • db.users.find({name: /jia$/})?- 查詢 name 中以 jia?結尾的數據
// 查詢 name 等于 jia 的數據
> db.users.find({name: "jia"})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
// 查詢 name 中包含 jia 的數據
> db.users.find({name: /jia/})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia", "age" : 49, "tel" : "0730-1234" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
// 查詢 name 中以 jia 結尾的數據
> db.users.find({name: /jia$/})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia", "age" : 49, "tel" : "0730-1234" }
多條件

db.users.find({$or: [{age: 19}, {name: 'jia'}]})?查詢 age=19 或 name=jia

// 查詢 age=19 或 name=jia
> db.users.find({$or: [{age: 19}, {name: 'jia'}]})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
列過濾
  • db.users.find({}, {name: 1})?- 只顯示 name 這個字段。默認主鍵回返回。1 是顯示,0指不顯示
  • db.users.find({}, {name: 1, age: 1, _id: 0})?- 只要 name 和 age 字段,主鍵不要
// 只顯示 name 這個字段。默認主鍵回返回
> db.users.find({}, {name: 1})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali" }
// 只顯示 name 這個字段,主鍵也不要
> db.users.find({}, {name: 1, _id: 0})
{ "name" : "peng" }
{ "name" : "jia" }
{ "name" : "li" }
{ "name" : "pengjia" }
{ "name" : "pengjiali" }
{ "name" : "jiali" }
// 只要 name 和 age 字段,主鍵不要
> db.users.find({}, {name: 1, age: 1, _id: 0})
{ "name" : "peng", "age" : 19 }
{ "name" : "jia", "age" : 29 }
{ "name" : "li", "age" : 39 }
{ "name" : "pengjia", "age" : 49 }
{ "name" : "pengjiali", "age" : 59 }
{ "name" : "jiali", "age" : 69 }
排序

通過?db.users.find().sort({age: -1})?執行 age 逆序,正序則為1。

// age 逆序
> db.users.find({}, {age:1}).sort({age: -1})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "age" : 69 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "age" : 59 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "age" : 49 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "age" : 39 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "age" : 29 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "age" : 19 }
// age 正序
> db.users.find({}, {age:1}).sort({age: 1})
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "age" : 19 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "age" : 29 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "age" : 39 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "age" : 49 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "age" : 59 }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "age" : 69 }
分頁

分頁可以通過 skip 和 limit實現。例如?db.users.find().skip(2).limit(2)?查詢第二頁。跳過2條,查詢2條。

> db.users.find()
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li", "age" : 39, "tel" : "0730-1233" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia", "age" : 49, "tel" : "0730-1234" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
// 查詢前3條
> db.users.find().limit(3)
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li", "age" : 39, "tel" : "0730-1233" }
// 第一頁。跳過0條,查詢2條
> db.users.find().skip(0).limit(2)
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"), "name" : "peng", "age" : 19, "tel" : "0730-1231" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048b"), "name" : "jia", "age" : 29, "tel" : "0730-1232" }
// 第二頁。跳過2條,查詢2條
> db.users.find().skip(2).limit(2)
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048c"), "name" : "li", "age" : 39, "tel" : "0730-1233" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048d"), "name" : "pengjia", "age" : 49, "tel" : "0730-1234" }
// 第三頁。跳過4條,查詢2條
> db.users.find().skip(4).limit(2)
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
// 先 age 逆序,在取2條
> db.users.find().sort({age: -1}).skip(0).limit(2)
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048f"), "name" : "jiali", "age" : 69, "tel" : "0730-1236" }
{ "_id" : ObjectId("643bb3dfd21fdd4d6f0b048e"), "name" : "pengjiali", "age" : 59, "tel" : "0730-1235" }

通過 count() 查詢記錄數,例如?db.users.find({name: 'jia'}).count()

// 總共 6 條
> db.users.find().count()
6
// 符合條件的共 1 條
> db.users.find({name: 'jia'}).count()
1
> db.users.find({name: /jia/}).count()
4

db.users.findOne()?- 查詢第一條

// 查詢第一條
> db.users.findOne()
{"_id" : ObjectId("643bb3dfd21fdd4d6f0b048a"),"name" : "peng","age" : 19,"tel" : "0730-1231"
}

項目目錄劃分

程序那么復雜,不可能全寫在一起,筆者做如下分層:

  • 路由層?- 匹配路由,調用控制層
  • 控制層?- 取得前端請求數據,加工處理,比如調用數據庫(services層),在返回數據給前端
  • 服務層?- 引用創建的數據庫模型,對數據進行增刪改查
  • 模型層?- 創建數據庫模型(這里是創建表)

用戶模塊為例,在這4層中分別創建如下 js:

- services            // 服務層- UserService.js    // User 模塊的服務層
- routes              // 路由- UserRouter.js     // User 模塊的路由。比如登錄、登錄
- models              // 模型層- UserModel.js      // User Model
- controllers         // 控制層- UserController.js 

連接數據庫

前面我們操作數據庫是直接進入 mongo shell 操作:

// 創建并切換到數據庫 pjl_db
use pjl_db// 創建 users 表(這里叫集合)
db.createCollection("users")

現在我們需要通過 node 來操作數據庫。

啟動mongo服務

通過?mongod --dbpath=/var/lib/mongodb --bind_ip=0.0.0.0 --port=27017?啟動mongo服務(未設置數據庫密碼)。其中?0.0.0.0?用戶遠程連接,端口是?27017

如果需要后臺啟動(關閉終端服務也不會停止),需要指定日志路徑,就像這樣:

root@linux:/home/pjl# mongod --dbpath=/var/lib/mongodb --fork --logpath=/var/log/mongodb/mongodb.log --bind_ip=0.0.0.0 --port=27017
about to fork child process, waiting until server is ready for connections.
forked process: 133354
child process started successfully, parent exiting

查看 mongod 進程:

root@linux:/home/pjl# ps aux |grep mongod
root      133354  7.5  1.5 976348 62496 ?        Sl   09:46   0:00 mongod --dbpath=/var/lib/mongodb --fork --logpath=/var/log/mongodb/mongodb.log --bind_ip=0.0.0.0 --port=27017
root      133383  0.0  0.0  12120   716 pts/0    S+   09:47   0:00 grep --color=auto mongod
root@linux:/home/pjl#

Tip:還可以通過指定配置文件啟動:

root@linux:/home/pjl# mongod -f /etc/mongodb.conf
// 沒反應,通過 `tail -10 日志` 能看到輸出

另起窗口進入 mongo shell,運行?show dbs?報錯如下:

// 筆者將配置文件中端口改為 27027
root@linux:/var/log/mongodb# mongo --port=27027
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27027/
Implicit session: session { "id" : UUID("dc184887-824d-474a-a942-3d42ff1a21bf") }
MongoDB server version: 3.6.8
> show dbs
2023-04-21T09:52:04.824+0800 E QUERY    [thread1] Error: listDatabases failed:{"ok" : 0,"errmsg" : "there are no users authenticated","code" : 13,"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
shellHelper.show@src/mongo/shell/utils.js:860:19
shellHelper@src/mongo/shell/utils.js:750:15
@(shellhelp2):1:1
>

網友說是?安裝mongo數據庫時,配置文件中加了安全權限的設置,解決請看這里

安裝 mongoose

通過?npm i mongoose -D?安裝 mongoose —— Mongoose is a MongoDB object modeling tool)。

通過 mongoose 操作數據庫非常方便

連接數據庫

連接數據庫很簡單,只需要先啟動數據庫服務,然后在啟動應用前連接數據庫即可。代碼如下:

// bin/www.jsvar http = require('http');
+ // 引入數據庫
+ require('../config/db.config')
var port = normalizePort(process.env.PORT || '3000');
// config/db.config.jsconst mongoose = require("mongoose")
// mongo服務 ip
mongoose.connect("mongodb://192.168.1.223:27017/pjl_db")
mongoose.connection.once("open", () => {console.log('數據庫連接成功')
})

通過 mongo shell 查到目前只有3個數據庫:

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

啟動應用,控制臺輸出?數據庫連接成功:

PS E:\spug-back-end> npm run start> spug-back-end@0.0.0 start
> nodemon ./bin/www[nodemon] 2.0.22
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node ./bin/www`
數據庫連接成功

發現 pjl_db 數據庫自動被創建。

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
pjl_db  0.000GB

Tip:有了數據庫,還得需要表才能對數據進行增、刪、改、查。在 mongoose 中,需要創建一個 model(模型),可以把他當做一張表(或一條記錄),比如下文登錄模塊的?UserModel.js?就是一個 model,向 model 插入一條數據時,mongoose 會自動創建一張名為 users 的表(或集合)。

登錄

這里我們完成系統登錄模塊的開發。

app.js

app.js 引入用戶路由。

// app.js
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
+ const UserRouter = require('./routes/UserRouter')app.use('/users', usersRouter);
+ app.use(UserRouter);

UserRouter.js

定義登錄路由(/user/login),路由匹配成功,進入控制層處理。

// routes/UserRouter.js// 用戶路由
var express = require('express');
var router = express.Router();
const UserController = require('../controllers/UserController.js')
/* POST users listing. */
router.post('/user/login', UserController.login);module.exports = router;

UserController.js

控制層調用服務層,如果數據庫能通過用戶名和密碼查詢到該用戶則表明登錄成功,否則返回用戶名密碼不匹配

// controllers/UserController.jsconst UserService = require('../services/UserService')const UserModel = require('../models/UserModel')
const UserController = {login: async (req, res) => {// req.body - 例如 {"username":"pjl","password":"123456"}console.log('res.body', JSON.stringify(res.body))var result = await UserService.login(req.body)if(result.length === 0){res.send({code: '-1',error: '用戶名密碼不匹配'})}else{res.send({code: '0',error: ''})}}
}module.exports = UserController

UserService.js

模型層通過 model 查找數據庫

// services/UserService.jsconst UserModel = require('../models/UserModel.js')
const UserService = {login: async ({username, password}) => {return UserModel.find({username,password})}
}module.exports = UserService

UserModel.js

mongoose 通過 model 創建表。

// models/UserModel.js// model 與表一一對應
const mongoose = require('mongoose')
const Schema = mongoose.Schema
// 通過 schema 限制一下集合(表),否則什么都能傳入,太自由了不好
const Usertype = {username: String,password: String,// 性別gender: Number,// 頭像avatar: String,// 角色role: Number, // 管理員1,編輯2
}const UserModel = mongoose.model("user", new Schema(Usertype))
module.exports = UserModel

測試

這里筆者在 git bash 中使用?curl(客戶端的url) 模擬登錄(post 用戶名+密碼):

Administrator@ ~/Desktop
$ curl -X POST -d 'username=pjl' -d 'password=123456' http://localhost:3000/user/login% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100    76  100    48  100    28   1425    831 --:--:-- --:--:-- --:--:--  2533{"code":"-1","error":"用戶名密碼不匹配"}

由于 users 表中沒有數據,當然也就查詢不到(返回?{"code":"-1","error":"用戶名密碼不匹配"})。

筆者手動插入該條用戶信息:

> use pjl_db
switched to db pjl_db
> db.users.save({username: 'pjl', password: '123456'})
WriteResult({ "nInserted" : 1 })

再次登錄就能查詢到?{"code":"0","error":""}:? ?

Administrator@ ~/Desktop
$ curl -X POST -d 'username=pjl' -d 'password=123456' http://localhost:3000/user/login% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100    51  100    23  100    28   1730   2106 --:--:-- --:--:-- --:--:--  5100{"code":"0","error":""}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41156.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41156.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41156.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

selenium 選定ul-li下拉選項中某個指定選項

場景&#xff1a;selenium的下拉選項是ul-li模式&#xff0c;選定某個指定的選項。 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 顯示等待def select_li(self, text, *ul_locator):"…

六圖備份 大容量圖片

1.1、切割&#xff08;9*16&#xff09; # 參考網址&#xff1a;https://blog.csdn.net/weixin_42182534/article/details/125773141?ops_request_misc&request_id&biz_id102&utm_termpython%E6%88%AA%E5%8F%96%E5%9B%BE%E7%89%87%E7%9A%84%E4%B8%80%E9%83%A8%E5%…

為什么在Spring中使用@Autowired時會提示Field injection is not recommended 而@Resource不會

在使用IDEA進行開發時&#xff0c;在字段上使用Spring的依賴注入注解Autowired后會出現如下警告 Field injection is not recommended (字段注入是不被推薦的) 這個原因具體可以看看&#xff1a; 【注解使用】使用Autowired后提示&#xff1a;Field injection is not recomme…

【抖音小玩法-彈幕游戲】開發者功能測試報告提交模板

背景 字節有明確的要求&#xff0c;準入和準出更加嚴格&#xff0c;要求有明確的測試報告。格式如下&#xff1a; *本文參考字節wiki&#xff1a;開發者功能測試報告提交模板 網絡兼容性 請確認在以下網絡類型驗證過插件功能 WIFI 4G 測試機型 請羅列驗證過的雙端機型 An…

python+django+mysql高校校園外賣點餐系統--計算機畢設項目

本文的研究目標是以高校校園外賣點餐為對象&#xff0c;使其高校校園外賣點餐為目標&#xff0c;使得高校校園外賣點餐的信息化體系發展水平提高。論文的研究內容包括對個人中心、美食分類管理、用戶管理、商家管理、美食信息管理、工作人員管理、安全檢查管理、系統管理、訂單…

時序預測 | MATLAB實現基于GRU門控循環單元的時間序列預測-遞歸預測未來(多指標評價)

時序預測 | MATLAB實現基于GRU門控循環單元的時間序列預測-遞歸預測未來(多指標評價) 目錄 時序預測 | MATLAB實現基于GRU門控循環單元的時間序列預測-遞歸預測未來(多指標評價)預測結果基本介紹程序設計參考資料 預測結果 基本介紹 1.Matlab實現GRU門控循環單元時間序列預測未…

復數混頻器、零中頻架構和高級算法開發

文章里講解了關于射頻IQ調制器、零中頻架構相關的原理及技術&#xff0c;全都是干貨&#xff01;其實好多同行對軟件無線電的原理、IQ調制、鏡像抑制都是一知半解&#xff0c;知其然不知其所以然。好好研讀這篇文章&#xff0c;相信會讓你有種恍然大悟的感覺。 RF工程常被視為…

Shell學習筆記之基礎部分

Shell基礎&#xff1a; 查看操作系統支持的shell&#xff1a; [rootrhel9 ansible]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bashShell的基本元素&#xff1a; 聲明&#xff1a;聲明用哪個命令解釋器來解釋并執行當前腳本文件中的語句&#xff0c;一般寫的…

大語言模型與語義搜索;釘釘個人版啟動內測,提供多項AI服務

&#x1f989; AI新聞 &#x1f680; 釘釘個人版啟動內測&#xff0c;提供多項AI服務 摘要&#xff1a;釘釘個人版正式開始內測&#xff0c;面向小團隊、個人用戶、高校大學生等人群。該版本具有AI為核心的功能&#xff0c;包括文生文AI、文生圖AI和角色化對話等。用戶可通過…

【IEEE會議】第二屆IEEE云計算、大數據應用與軟件工程國際學術會議 (CBASE2023)

第二屆IEEE云計算、大數據應用與軟件工程國際學術會議 (CBASE2023&#xff09; 隨著大數據時代的到來&#xff0c;對數據獲取的隨時性和對計算的需求也在逐漸增長。為推動大數據時代的云計算與軟件工程的發展&#xff0c;促進該領域學術交流&#xff0c;在CBASE 2022成功舉辦的…

設計模式——經典單例

0、核心要素 // 構造、析構函數私有化&#xff08;一個進程只允許一個對象存在&#xff09; // 對象私有化、靜態化&#xff08;因為接口靜態函數&#xff09; // 對象調用接口靜態化&#xff08;因為靜態函數脫離了類對象&#xff0c;可以直接調用&#xff09; 一、懶漢 唯…

如何更好的維護自己的電腦?

我的筆記本電腦 我使用的華碩天選3是一款游戲本&#xff0c;搭載了英特爾酷睿i7-12700H處理器&#xff0c;16GB內存&#xff0c;512GB固態硬盤和NVIDIA GeForce RTX 3050顯卡。屏幕尺寸為15.6英寸&#xff0c;分辨率為2560x1440。對于日常使用和工作學習娛樂都能滿足要求。 日常…

基于docker搭建pytest自動化測試環境(docker+pytest+jenkins+allure)

pytest搭建自動化測試環境&#xff08;dockerpytestjenkinsallure&#xff09; 這里我以ubuntu18為例 如果有docker環境&#xff0c;可以直接拉取我打包好的鏡像docker pull ziyigun/jenkins:v1.0 1 搭建Docker 1.1 安裝docker # 配置docker安裝環境 sudo apt-get install ap…

潤和軟件HopeStage操作系統正式上架阿里云、華為云、騰訊云商店

近日&#xff0c;潤和軟件HopeStage操作系統正式上架阿里云、華為云、騰訊云商店。 隨著科技的發展&#xff0c;云服務成為現代社會信息和資訊的交換、共享、存儲、檢索、應用等重要方式。阿里云、華為云、騰訊云作為我國云服務市場三巨頭&#xff0c;其云商店產品全面覆蓋云、…

Nvidia Jetson 編解碼開發(1)介紹

前言 由于項目需要,需要開發Jetson平臺的硬件編解碼; 優化CPU帶寬,后續主要以介紹硬件編解碼為主 1.Jetson各平臺編解碼性能說明 如下是拿了Jetson nano/tx2/Xavier等幾個平臺做對比; 這里說明的編解碼性能主要是對硬件來說的 2. 編解碼實現說明 2.1 軟件編解碼 優點:…

Idea中隱藏指定文件或指定類型文件

Setting ->Editor ->Code Style->File Types → Ignored Files and Folders輸入要隱藏的文件名&#xff0c;支持*號通配符回車確認添加

Windows權限維持—自啟動映像劫持粘滯鍵輔助屏保后門WinLogon

Windows權限維持—自啟動&映像劫持&粘滯鍵&輔助屏保后門&WinLogon 1. 前置2. 自啟動2.1. 路徑加載2.1.1. 放置文件2.1.2. 重啟主機 2.2. 服務加載2.2.1. 創建服務2.2.2. 查看服務2.2.3. 重啟主機 2.3. 注冊表加載2.3.1. 添加啟動項2.3.2. 查看注冊表2.3.3. 重啟…

YOLOv5基礎知識入門(7)— NMS(非極大值抑制)原理解析

前言&#xff1a;Hello大家好&#xff0c;我是小哥談。NMS是指非極大值抑制&#xff08;non maximum suppression&#xff09;&#xff0c;它是一種常用于物體檢測任務的算法。在物體檢測中&#xff0c;通常會有多個預測框&#xff08;bounding box&#xff09;被提議出來&…

機器學習深度學習——transformer(機器翻譯的再實現)

&#x1f468;?&#x1f393;作者簡介&#xff1a;一位即將上大四&#xff0c;正專攻機器學習的保研er &#x1f30c;上期文章&#xff1a;機器學習&&深度學習——自注意力和位置編碼&#xff08;數學推導代碼實現&#xff09; &#x1f4da;訂閱專欄&#xff1a;機器…

【論文閱讀】 Model Sparsity Can Simplify Machine Unlearning

Model Sparsity Can Simplify Machine Unlearning 背景主要內容Contribution Ⅰ&#xff1a;對Machine Unlearning的一個全面的理解Contribution Ⅱ&#xff1a;說明model sparsity對Machine Unlearning的好處Pruning方法的選擇sparse-aware的unlearning framework Experiments…