重拾MongoDB从CRUD开始

几年前,大概还是和刚刚在国内崭露头角的时候。作为一个刚入行前端的小白开发者,也曾热血澎湃的对它们进行过一番了解。做过的记事本,写过小代码。但是,后来由于工作的原因,逐渐将重心放在了前端开发上,对于这些更贴近后端的内容,便渐渐的疏远变得陌生。现在大前端呼声渐长,全栈工程师越来越受欢迎,突然发现想要用它们来做一些小应用,却发现不知该如何下手了,索性回到原点从零开始。

今天就和大家一起聊一聊我使用编写一个超级简单的文章管理系统的过程。原本想做一个简单的博客系统,但觉得用户管理模块太重,就把它砍掉了,直接进入正题实现文章的增、删、改、查。

开始之前,我们先来解决的问题。不嫌麻烦的话,我们可以在自己的电脑上安装数据库,通过本地()连接访问。安装和配置过程比较简单,网上也很多教程,此处不做赘述。另外,在的官方文档中提到了一个Mongo云数据库服务可以提供运行、管理、监控Mongo数据库等服务——,并且还有免费项目,简直是我等初学者的福音。不过Atlas也有一些缺点,比如:访问速度比较慢、全英文界面等,大家视情况选择吧。

在Atlas上申请配置完成之后,我们可以得到一个数据库访问地址,类似,在接下来的功能中我们可以通过这个地址连接到MongoDB集群。

Koa建立Web应用

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

正如官网描述,是一个新的框架,因此,用搭建一个应用非常简单。考虑到我们会有多个页面的场景,因此需要使用中间件来处理路由,一个超级简单的应用如下:

// index.js

constKoa =require('koa');

constMongoClient = Mongo.MongoClient;

constapp =newKoa();

constRoute =newRouter();

Route.get('/', (ctx) => {

ctx.body ='Index';

});

app.use(Route.routes())

.use(Route.allowedMethods())

.listen(3003, () => {

console.log('Server is running at: 127.0.0.1:3003');

});

只需在命令行中执行,然后通过浏览器访问就可以访问应用首页了。

连接MongoDB

前面我们提到在Atlas中配置完后可以得到一个连接MongoDB的链接,在Node应用中我们可以通过MongoDB官方提供的包来连接数据库。

首先,通过安装驱动包:

npm install --save mongodb

然后在应用中引入该包来进行MongoDB数据库连接:

constMongo =require('mongodb');

constMongoClient = Mongo.MongoClient;

constdbUrl ='mongodb://:

@:27017';// 替换成自己的

constdbName ='databasename';// 替换成自己的

constcollName ='collectionname';// 替换成自己的

MongoClient.connect(dbUrl, {useNewUrlParser:true}, (err, db) => {

console.log(db);

// 操作数据库,完成增删改查

db.close();// 处理完别忘记关闭数据库连接

});

通过以上代码便可以实现MongoDB的链接,但是,我们现在还什么都没有做。

操作数据库

以发布文章功能为例,首先我们需要通过建立文章发布请求的路由,将该请求提交的数据存入具体的集合(‘数据表’),完成后告知浏览器处理结果。顺便说一句,往服务器提交大量数据通常使用方式,而本身并未对如何处理post请求数据做封装,因此我们需要依赖另一个中间件,类似的插件还有很多,可自行扩展。

Route.post('/post',asyncctx => {

constbdo = ctx.request.body || {};

awaitnewPromise(resolve=>{

MongoClient.connect(dbUrl, {useNewUrlParser:true}, (err, db) => {

if(err) {

ctx.body =JSON.stringify({code:1});

resolve();

return;

}

constblog = db.db(dbName);

constcoll = blog.collection(collName);

coll.insertOne({ ...bdo,timestamp:newDate().getTime() }).then((res) =>{

ctx.body =JSON.stringify({code:, ...bdo });

db.close();

resolve();

});

});

});

});

这里需要注意几个问题。

首先,的响应不会等待异步操作的处理结果,如果我们的处理逻辑中有异步逻辑,需要利用自行处理,否则将得不到正确的处理结果。

其次,便是必须放在的函数内部才可以,否则会出现异常。而终止的条件是Promise的方法被执行。

最后,模块对数据库的操作方法提供了两种模式:和模式,我们可以根据自己的情况和使用习惯自行选择。为了更清楚的描述两种类型,以上代码分别使用了两种模式,方法的调用使用的是回调模式,而其内部往数据库中插入一条记录的方法则是使用的Promise模式。

另外,读取数据库中的数据方法与的使用方法类似,不同的是该方法返回的是一个实例,我们可以进一步对查到的数据进行排序(),计算记录数(),遍历()等处理,也可以直接使用方法,转换为JSON数组进行处理,如:

// 读取文章列表

constresult = coll.find({}).sort({timestamp:-1});

result.toArray((err, res) =>{

res = res || [];

constlist = res.map(a=>{

return'

'+ a.title +'删除

';

});

constbd = fs.readFileSync('./static/list.html').toString('utf-8');

ctx.body = bd.replace(/\/g,'

'+ list.join('') +'

');

db.close();

resolve();

});

最后,我们来聊一聊删除功能。删除文章,必定需要先知道要删除哪一篇文章,否则就可能出现找不到或找错要删除的对象。因此,为了确保唯一性,我们使用文章记录的字段作为参数传递给删除路由。而在中,则根据接收到的id去查找对应的文章记录,执行删除操作:

Route.get('/del',asyncctx => {

constquery = ctx.query || {};

constaid = query.id ||'';// 从请求参数中获取文章ID

awaitnewPromise(resolve=>{

MongoClient.connect(dbUrl, {useNewUrlParser:true}, (err, db) => {

constblog = db.db(dbName);

constcoll = blog.collection(collName);

constrs = coll.deleteOne({_id: Mongo.ObjectId(aid)});

rs.then(res=>{

ctx.body = res.toString();

resolve();

});

});

});

});

同样,方法返回的也是一个Promise对象。而在上例中给方法传入了一个参数,这个参数就是查找被删除对象的条件,可由多个条件决定。需要注意的是,当我们通过或一些可视化工具(如:)查看数据记录的时候,你会发现字段的值是一个对象,而我们通过请求参数获得的是一个id字符串,因此我们需要使用方法进行转换,否则会找不到对应的记录。

而在Node.js执行环境中方法并不是一个内置方法,我们只能通过包来获取这个方法,如上代码所示:。

至此,增、删、查的功能都实现了,“改”就不多说了,用法都大同小异,其实关键是在官方文档中都有详细的描述。

最后,春节到了,祝大家新年快乐,阖家幸福,在胖三斤的过程中别忘记给自己充充电,哈哈哈…

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190131G1307H00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券