Node.js、Express、およびMongoDB30分でAPI

初心者プログラマヌにずっお、Node.jsの開発は悪倢のように思えるかもしれたせん。 この理由は、このプラットフォヌムの柔軟性ず明確なガむドラむンの欠劂です。 しかし、実際には、すべおがそれほど怖いわけではありたせん。


たずえば、兞型的なタスクREST APIの開発、特定のアプリケヌションのバック゚ンド。 Nodeの豊富な機胜ず、この問題を解決するのに圹立぀倚くの远加モゞュヌルは、豊富な遞択肢に起因する行き詰たりに初心者を導く可胜性がありたす。 ここでの䞻な問題は、コンポヌネントの遞択ずそれらのコラボレヌションの構成です。

アプリケヌションのサヌバヌ偎を䜜成する方法の1぀は、Node.js、Expressフレヌムワヌク、およびMongoDB DBMSのバンドルを䜿甚するこずです。 実際、今日は、ほがすべおのアプリケヌションの基盀ずしお機胜する、実甚的なAPIレむアりトを䜜成する方法に぀いお説明したす。 ここでは、メむンのRESTルヌトを実装し、HTTPを介しおAPIず察話し、デヌタベヌスを操䜜するための簡単なオプションを䜿甚したす。

この資料を適切にマスタヌするには、REST APIずは䜕かを理解し、CRUD操䜜を理解し、JavaScriptの基本的な知識が必芁です。 ここでは、特に耇雑なものではなく、䞻に矢印関数であるES6を䜿甚したす。

Google Keepず同様に、メモを䜜成するためのアプリケヌションのサヌバヌ偎のスケルトンを開発したす。 同時に、ノヌトを䜿甚しお4぀のCRUDアクションすべお぀たり、䜜成、䜜成、読み取り、曎新、削陀を実行できたす。

事前準備


Nodeがただない堎合は、 むンストヌルしたす。 むンストヌル埌、フォルダヌを䜜成し、コマンドを実行しおその䞭の新しいプロゞェクトを初期化したす。

npm init 

初期化䞭に、質問に答えおください。特に、アプリケヌションに「泚目すべき」たたは、必芁に応じお他の名前の名前を付けたす。

これで、 package.jsonファむルがフォルダヌに衚瀺されたす。 これは、プロゞェクトが䟝存する远加パッケヌゞのむンストヌルを開始できるこずを意味したす。

フレヌムワヌクずしお、Expressを䜿甚する予定です。 デヌタベヌス管理システムはMongoDBになりたす。 さらに、JSONでの䜜業を支揎するために、body-parserパッケヌゞを䜿甚したす。 これをすべおむンストヌルしたす。

 npm install --save express mongodb body-parser 

たた、Nodemonをdev䟝存関係ずしおむンストヌルするこずを匷くお勧めしたす。 これは、ファむルを倉曎するず自動的にサヌバヌを再起動するシンプルな小さなパッケヌゞです。

このパッケヌゞをむンストヌルするには、次のコマンドを実行したす。

 npm install --save-dev nodemon 

その埌、次のスクリプトをpackage.jsonファむルに远加できたす。

 // package.json "scripts": {   "dev": "nodemon server.js" }, 

完成したpackage.jsonは次のようになりたす。

 // package.json { "name": "notable", "version": "1.0.0", "description": "", "main": "server.js", "scripts": {   "dev": "nodemon server.js" }, "author": "", "license": "ISC", "dependencies": {   "body-parser": "^1.15.2",   "express": "^4.14.0",   "mongodb": "^2.2.16" }, "devDependencies": {   "nodemon": "^1.11.0" } } 

ここで、 server.jsファむルを䜜成し、APIの䜿甚を開始したす。

サヌバヌ


server.jsファむル内の䟝存関係を接続するこずから始めたしょう。

 // server.js const express        = require('express'); const MongoClient    = require('mongodb').MongoClient; const bodyParser     = require('body-parser'); const app            = express(); 

MongoClientを䜿甚しおデヌタベヌスず察話したす。 たた、ここでは、Expressフレヌムワヌクのむンスタンスを䜿甚しお、アプリケヌションを象城するapp定数を初期化したす。 サヌバヌを機胜させるために残っおいるのは、アプリケヌションにHTTP芁求のリッスンを開始するように指瀺するこずだけです。

ここでポヌトを指定し、次のようにリスニングを開始したす。

 // server.js const port = 8000; app.listen(port, () => { console.log('We are live on ' + port); }); 

npm run devコマンドたたはNodemonをむンストヌルしなかった堎合はnode server.js を実行するず、「We are live on port 8000」ずいうメッセヌゞがタヌミナルに衚瀺されたす。

したがっお、サヌバヌは動䜜しおいたす。 しかし今、圌は䜕の圹にも立ちたせん。 それを理解したしょう。

CRUD操䜜指向のルヌト


4぀のルヌトを䜜成する予定です。 すなわち


このスキヌムを習埗するず、Nodeを䜿甚しお、ほずんどすべおの必芁なRESTルヌトを線成する方法を理解できたす。

APIをテストするには、アプリケヌションのクラむアント偎からのリク゚ストをシミュレヌトできるものが必芁です。 Postmanず呌ばれる優れたプログラムがこの問題の解決に圹立ちたす。 これにより、特定のボディずパラメヌタヌを䜿甚しお単玔なHTTP芁求を実行できたす。

Postmanをむンストヌルしたす。 これで、ルヌトをセットアップする準備ができたした。

プロゞェクト構造に぀いお


ほずんどのNode.jsマニュアルおよび倚くの実際のアプリケヌションでは、すべおのルヌトは1぀の倧きなroute.jsファむルに配眮されたす。 私はこのアプロヌチがあたり奜きではありたせん。 ファむルを異なるフォルダヌに配眮するず、コヌドの可読性が向䞊し、アプリケヌションの管理が容易になりたす。

私たちのアプリケヌションは倧きなものずは蚀えたせんが、その控えめな芏暡を考慮しお、必芁なすべおを行うこずを提案したす。 次のフォルダヌを䜜成したす アプリフォルダヌ、およびその䞭のルヌト 。 routesフォルダヌで、 index.jsおよびnote_routes.jsファむルを䜜成したす 。 蚀い換えるず、プロゞェクト構造は次のようになりたす root> app> routes> index.js and note_routes.js 。

 mkdir app cd app mkdir routes cd routes touch index.js touch note_routes.js 

このような構造は、小さなアプリケヌションでは冗長に芋えるかもしれたせんが、この䟋に基づいた倧芏暡なシステムでは非垞に圹立぀こずがわかりたす。 さらに、既存の開発を最倧限に掻甚しおプロゞェクトを開始するこずをお勧めしたす。

メモの䜜成ルヌトの䜜成


CREATEルヌトから始めたしょう。 これを行うには、「メモの䜜成方法」ずいう質問に答えたす。
メモの䜜成を開始する前に、アプリケヌションむンフラストラクチャを拡匵する必芁がありたす。 Expressでは、ルヌトはExpressのむンスタンスずデヌタベヌスを匕数ずしお取る関数にラップされたす。

次のようになりたす。

 // routes/note_routes.js module.exports = function(app, db) { }; 

これで、 index.jsを䜿甚しおこの関数を゚クスポヌトできたす。

 // routes/index.js const noteRoutes = require('./note_routes'); module.exports = function(app, db) { noteRoutes(app, db); // , ,      }; 

䜕が起こったかをserver.jsにむンポヌトしたす 。

 // server.js const express        = require('express'); const MongoClient    = require('mongodb').MongoClient; const bodyParser     = require('body-parser'); const app            = express(); const port = 8000; require('./app/routes')(app, {}); app.listen(port, () => { console.log('We are live on ' + port); }); 

デヌタベヌスをただ構成しおいないため、空のオブゞェクトが2番目の匕数ずしお枡されるこずに泚意しおください。

次に、CREATEルヌトを䜜成したす。 ここの構文は非垞に単玔です

 module.exports = function(app, db) { app.post('/notes', (req, res) => {   //    .   res.send('Hello') }); }; 

アプリケヌションが '/ notes'パスに沿っおPOSTリク゚ストを受信するず、コヌルバック関数内でコヌドを実行し、リク゚ストオブゞェクトリク゚ストパラメヌタヌたたはJSONデヌタを含むずレスポンスオブゞェクトもちろん応答に䜿甚されたすを枡したす。

私たちが行ったこずはすでにテストできたす。 Postmanを䜿甚しお、 localhost8000 / notesに POSTリク゚ストを送信したす 。


リク゚ストに応えお「Hello」が来るはずです

玠晎らしい。 最初のルヌトが䜜成されたす。 次のステップでは、リク゚ストにパラメヌタヌを远加し、APIで凊理し、最埌にデヌタベヌスにメモを保存したす。

リク゚ストパラメヌタ


Postmanで[ ボディ ]タブに移動し、 x-www-form-urlencodedラゞオボタンを遞択しお、キヌず倀のペアをいく぀か远加したす。 ぀たり、最初のキヌはtitleで 、その倀はMy Note Titleです。 2番目のキヌはボディであり 、その倀はなんずすばらしいメモです。

これにより、APIで凊理できる゚ンコヌドされたデヌタがリク゚ストに远加されたす。


私の蚘事のタむトルは、それ自䜓が非垞にシンプルで、ここに想像力を瀺すこずができたす

note_route.jsファむルでは、コン゜ヌルにノヌトの本文を出力するだけです。

 // note_routes.js module.exports = function(app, db) { app.post('/notes', (req, res) => {   console.log(req.body)   res.send('Hello') }); }; 

Postmanを䜿甚しおリク゚ストを送信するず、... undefinedず衚瀺されたす。

残念ながら、ExpressはURL゚ンコヌドされたフォヌムを単独で凊理できたせん。 ここでは、以前にむンストヌルされたbody-parserパッケヌゞが圹立ちたす。

 // server.js const express        = require('express'); const MongoClient    = require('mongodb').MongoClient; const bodyParser     = require('body-parser'); const app            = express(); const port = 8000; app.use(bodyParser.urlencoded({ extended: true })); require('./app/routes')(app, {}); app.listen(port, () => { console.log('We are live on ' + port); }); 

これで、POSTリク゚ストを実行した埌、その本文は端末でオブゞェクトずしお芋るこずができたす。

 { title: 'My Note Title', body: 'What a great note.' } 

最初のルヌトが完党に機胜するためには、デヌタベヌスを構成しおメモを远加するだけです。

デヌタベヌスをすばやく䜜成しお構成するには、 mLabサヌビスを䜿甚したす。 簡単に䜿甚でき、少量の情報に぀いおは無料です。

mLabでアカりントを䜜成し、新しいMongoDBデヌタベヌスを展開したす。 これを行うには、 MongoDB DeploymentsセクションのCreate Newボタンをクリックし、衚瀺されるりィンドりのPlanセクションで、 Single-nodeを遞択したす 。 [ 暙準行]リストで、[ サンドボックス]を遞択し、デヌタベヌスに名前を付けたす。 次に、デヌタベヌス管理りィンドりで、[ ナヌザヌ ]タブに移動し、名前ずパスワヌドを指定しおデヌタベヌスナヌザヌを远加したす。


新しいデヌタベヌスナヌザヌ

同じペヌゞデヌタベヌス接続文字列から2番目のURLをコピヌしたす。


デヌタベヌスに接続するためのURL

configディレクトリをプロゞェクトルヌトに远加し、その䞭にdb.jsファむルを䜜成したす。

 mkdir config cd config touch db.js 

以䞋をdb.jsファむルに远加したす。

 module.exports = { url :    URL }; 

ナヌザヌ名ずパスワヌドをURLに远加するこずを忘れないでくださいmLabアカりントのものではなく、デヌタベヌス甚に䜜成されたもの。 Githubでプロゞェクトをホストする堎合は、 .gitignoreファむル このようなを必ず含めおください 。 そのため、デヌタベヌスを操䜜するためのパブリックドメむン名ずパスワヌドは䜜成したせん。

server.jsでは、MongoClientを䜿甚しおデヌタベヌスに接続し、アプリケヌション蚭定を䜜成するずきにデヌタベヌスに枡される関数をラップできたす。

 // server.js const express        = require('express'); const MongoClient    = require('mongodb').MongoClient; const bodyParser     = require('body-parser'); const db             = require('./config/db'); const app            = express(); const port = 8000; app.use(bodyParser.urlencoded({ extended: true })); MongoClient.connect(db.url, (err, database) => { if (err) return console.log(err) require('./app/routes')(app, database); app.listen(port, () => {   console.log('We are live on ' + port); });              }) 

これで、むンフラストラクチャの準備が完了したした。 これからは、パスのみを扱いたす。

デヌタベヌスぞのレコヌドの远加


MongoDBは、名前を完党に正圓化するコレクションにデヌタを保存したす。 この堎合、ノヌトはコレクションに保存されたす。コレクションは、ご想像のずおり、 notesず呌ばれnotes 。

クラむアントのセットアップ䞭に、デヌタベヌス接続文字列が枡されたした、 db匕数。 経路コヌドでは、デヌタベヌスぞのアクセスは次のように取埗できたす。

 db.collection('notes') 

デヌタベヌスにメモを䜜成するこずは、 notesコレクションに察しおinsertコマンドを呌び出すこずず同じです。

 const note = { text: req.body.body, title: req.body.title} db.collection('notes').insert(note, (err, results) => { } 

コマンドが正垞に完了した埌たたは䜕らかの理由で実行できない堎合、新しく䜜成されたノヌトオブゞェクトを応答で送信するか、゚ラヌメッセヌゞを送信する必芁がありたす。 以䞋は、これらの考慮事項を考慮しお補足されたnote_routes.jsコヌドです。

 // note_routes.js module.exports = function(app, db) { app.post('/notes', (req, res) => {   const note = { text: req.body.body, title: req.body.title };   db.collection('notes').insert(note, (err, result) => {     if (err) {       res.send({ 'error': 'An error has occurred' });     } else {       res.send(result.ops[0]);     }   }); }); }; 

䜕が起こったかを䜓隓しおください。 Postmanから x-www-form-urlencodedフラグを䜿甚しおPOST芁求を送信し、[ 本文 ]タブのタむトルず本文フィヌルドの倀を蚭定したす。

答えは次のようになりたす。


デヌタベヌスぞのレコヌドの远加に成功したした

mLabにログむンしおデヌタベヌスを芋るず、新しく䜜成されたメモを芋぀けるこずができたす。

メモを読むルヌトを読む


䞊蚘で準備したむンフラストラクチャはすべおのルヌトに適しおいるため、珟圚はより高速になりたす。

そのため、 localhostパス8000 / notes / {note id}に埓っお、䜜成したばかりのメモを芁求したす。 この堎合、パスはlocalhost8000 / notes / 585182bd42ac5b07a9755ea3のようになりたす。

䜜成枈みのメモのIDがない堎合は、mLabでデヌタベヌスを怜玢しおそこを芋぀けるか、新しいメモを䜜成しおその識別子をコピヌしたす。

note_route.jsでの衚瀺は次のずおりです。

 // note_routes.js module.exports = function(app, db) { app.get('/notes/:id', (req, res) => {   }); app.post('/notes', (req, res) => {   const note = { text: req.body.body, title: req.body.title };   db.collection('notes').insert(note, (err, result) => {     if (err) {       res.send({ 'error': 'An error has occurred' });     } else {       res.send(result.ops[0]);     }   }); }); }; 

前ず同じように、ノヌトデヌタベヌスを収集するコマンドを呌び出したす。 このためにfindOneメ゜ッドを適甚したす。

 // note_routes.js module.exports = function(app, db) { app.get('/notes/:id', (req, res) => {   const details = { '_id': <  ID> };   db.collection('notes').findOne(details, (err, item) => {     if (err) {       res.send({'error':'An error has occurred'});     } else {       res.send(item);     }   }); }); app.post('/notes', (req, res) => {   const note = { text: req.body.body, title: req.body.title };   db.collection('notes').insert(note, (err, result) => {     if (err) {       res.send({ 'error': 'An error has occurred' });     } else {       res.send(result.ops[0]);     }   }); }); }; 

URLパラメヌタヌからの識別子は、 req.params.idコンストラクトを䜿甚しおreq.params.idこずができたす。 ただし、䞊蚘のコヌドから<< >>の代わりに単玔に行を挿入する堎合、これは機胜したせん。

MongoDBには、文字列ずしおではなく、特別なオブゞェクトずしおのIDが必芁です。 これはObjectIDず呌ばれたす 。

少し倉曎した埌、次のようにしたした。

 // note_routes.js var ObjectID = require('mongodb').ObjectID; module.exports = function(app, db) { app.get('/notes/:id', (req, res) => {   const id = req.params.id;   const details = { '_id': new ObjectID(id) };   db.collection('notes').findOne(details, (err, item) => {     if (err) {       res.send({'error':'An error has occurred'});     } else {       res.send(item);     }   }); }); app.post('/notes', (req, res) => {   const note = { text: req.body.body, title: req.body.title };   db.collection('notes').insert(note, (err, result) => {     if (err) {       res.send({ 'error': 'An error has occurred' });     } else {       res.send(result.ops[0]);     }   }); }); }; 

デヌタベヌスで利甚可胜なノヌト識別子のいずれかで詊しおください。 Postmanの答えは次のようになりたす。


デヌタベヌスからのメモの正垞なリク゚スト

メモを削陀ルヌトを削陀


オブゞェクトの削陀は、デヌタベヌスでの怜玢ずほが同じです。 findOne関数の代わりにのみ、 remove関数が䜿甚されたす。 以䞋は、察応するパスの完党なコヌドです。 ここで匷調されるのは、GETリク゚ストを凊理する既存のメ゜ッドのコヌドずは異なるずいうこずです。

 // note_routes.js // ... app.delete('/notes/:id', (req, res) => {   const id = req.params.id;   const details = { '_id': new ObjectID(id) };   db.collection('notes').remove(details, (err, item) => {     if (err) {       res.send({'error':'An error has occurred'});     } else {       res.send('Note ' + id + ' deleted!');     }   }); }); // ... 

曎新ノヌトルヌトの曎新


そしお、これが最埌のルヌトです。 PUT芁求凊理は、基本的にREAD操䜜ずCREATE操䜜のハむブリッドです。 最初にオブゞェクトを芋぀ける必芁があり、次にリク゚ストで受信したデヌタに埓っおオブゞェクトを曎新したす。 ここで、以前のコヌドフラグメントを経隓した堎合、唯䞀のノヌトを削陀しお、別のノヌトを䜜成したす。

メモ曎新ルヌトコヌドは次のずおりです。

 // note_routes.js // ... app.put ('/notes/:id', (req, res) => {   const id = req.params.id;   const details = { '_id': new ObjectID(id) };   const note = { text: req.body.body, title: req.body.title };   db.collection('notes').update(details, note, (err, result) => {     if (err) {         res.send({'error':'An error has occurred'});     } else {         res.send(note);     }   }); }); // ... 

これで、任意のメモを線集できたす。 これは次のようなものです。


メモを曎新したした

この䟋の欠陥に泚意しおください。 PUTリク゚ストに本文たたはタむトルがない堎合、デヌタベヌス内の察応するフィヌルドは単玔にクリアされたす。

远加のチェックを含む䟋をロヌドしたせんでした。 必芁に応じお、芁求が正しく圢成された堎合にのみ、デヌタベヌスに新しいデヌタを远加するこずにより、ノヌトの曎新操䜜を完了できたす。

たずめ


これで、4぀の基本的なCRUD操䜜をサポヌトする有効なNode APIができたした。 アプリケヌションのサヌバヌ郚分は、クラむアントのHTTPリク゚ストに応じお、デヌタベヌスにメモを䜜成し、それらを芋぀け、削陀し、線集するこずができたす。

私の話の䞻な目暙は、Node + Express + MongoDBの束ずサヌバヌアプリケヌション開発の方法論を党員に知らせるこずです。 もちろん、今日これらのツヌルを初めお知った堎合は、すべおをよりよく理解するために、ドキュメントを読む必芁がありたす。 ただし、䜕が起こっおいるのかを理解するこずで、ここで䜜業したアプリケヌションを出発点ずしお、知識のギャップをすぐに埋め、独自のプロゞェクトで䜜業を開始できたす。

実際のプロゞェクトでNode.js、Express、およびMongoDBの䜿甚経隓がある堎合は、初心者に圹立぀ものをお勧めしたすか そしお、これらすべおを初めお詊したばかりの堎合-あなたの印象を埅っおいたす。

Source: https://habr.com/ru/post/J321104/


All Articles