mongoose续
前一篇笔记只是非常简单的说了下mongoose下怎样对collection进行增删查改,所以这里做做笔记说说别的开发过程中可能遇到的琐碎。
关于查询
安全
闲话不说,直接看图:
这个图在第二篇笔记里面见过。它有什么问题吗?没有,但是也许可以有:比如说,那个”_id”就是不需要的数据,如果所有的数据都直接这样返回,那么必然会存在一些商业机密信息暴露——尤其是你的user collections里面包含用户手机号码和地址时候。
我们来优化一下流程:
1 | router.get('/user', function(req, res, next) { |
当然,map可能不是非常优雅,但是,还有select可以做到限制字段输出,这里说map,是因为最初自己使用的这个办法处理问题。select具体后文有写到。
静态方法
很多时候状态作为数字存入数据库,做后端数据库的同学应该很熟悉,经常用前端模板渲染json到页面的前端ers也会非常熟悉。在mongoose里面也定义了这样一类方法。我们做个简单的例子
1 | var mongoose = require('mongoose'); |
除了这种最简单的静态方法,在静态方法中还可以调用model进行查询:
1 | schema.methods.sex = function(user){//假装数据里面已经有age属性了吧...这是一个获取相同性别人集合的一个方法 |
关于限制性查询
『SELECT * FROM table ORDER BY id』,想起这类查询,我就想起曾经学过的mysql和php,很熟悉的感觉,哈哈哈。
在mongoose里面当然不是这样查询了,作为一个框架,它必然也会提供类似这种Order By的排序方法。
我在网上找了个相对全的代码片段,就懒得自己写了:
1 | Person |
这里总结一下在查询过程中会遇到的情形:
- 属性值是确定的字符串,而不是一个区间时候,直接在find环节传递参数进去
- 第二个环节对有区间的数字这种进行限制,如代码中的gt和lt,代表意思是大于17小余66
- 限制查询条目用limit传入数字进行限制
- 最后,限制字段使用select传入使用空格分隔的字符串作为需要的字段
当然,如果是非常简单的查询,只是需要限制字段的话,可以这样:
1 | router.get('/user',"name age",function(req, res, next) { |
恩,这就是最开始的代码片段除了select的另外的一种解决办法。
查询的静态方法
最后说下查询的方法,查询可以使用的方法有三个
- find(query)
- findOne(query)
- findById(ObjectID)
find
find这个应该无需多说了,在前面已经有了太多例子了。
findOne
接受一个查询条件,返回单个数据,这个方法,在一些限制性的collection中非常有用,例如很多保存操作会在进行保存之前判断是否用重复,这个最常见的是管理员帐号collection限制用户名不能相同和用户注册collection限制手机和邮件不能相同。
findById(ObjectID)
应该来说这个性能最高。如果能获取ObjectID,使用它替代findOne,无需进行任何query查询直接获取结果。
关于增加
在mysql这类sql数据库里面,数据是强制限制的,如果不符合会被拒绝写入,但是mongoDB作为NoSql数据库是不限制类型的,这意味着当将mongoDB作为关系型数据库时候需要自己承担这个验证的过程,mongoose里面已经为我们做了这个接口:
1 | var conn = mongoose.connect('mongodb://que01:<youhost>:<youport>/learn'); |
关于更新
用关数据更新的Model辅助方法
- update()
- findOneAndUpdate() 这个之前有过演示
- findByIdAndUpdate()
这三个方法都接受相同的四个参数:
- conditions 查询条件
- update 一个对象,里面放想要设置的键值对
- options 一个对象,里面设置一些特殊的操作
- callback 回调函数,执行更新之后的回调
这里简单说下options这个选项,在三个方法中,它有所不同
options在update()中
safa
布尔值,是否抛出错误给callback,默认值是schema中设置的。如果没有设置,缺省值是trueupsert
布尔值,当没有匹配document是否新建一个,缺省值为falsemulti
布尔值,是否多个文档可以一起更新,默认为falsestrict
是否只有schema已定义的数据才能被保存,默认值是true
findOneAndUpdate()&findByIdAndUpdate中
new
布尔值,是否返回最初被修改过的document,默认为trueupsert
布尔值,如果查询文档不存在则新建一个,默认为falsesort
接受一个object,对查到的数据排序select
string,空格分隔的字段组成的字符串
更新步骤
更新数据是个复合动作,包括三个动作:查、改、存。所以说,即使不实用update方法,使用find,手动实现修改后,save()之,也是一个完整的更新过程。
但是这里我们来使用update更新数据会更快,更方便(其实更方便我觉得是最重要的):
1 | User.update( |
是不是很简单?update将读、改、保存合为一体了,这就是它的『快』,但是除了这个快之外,还有一个更方便地方:
它只是更新了lastLogin值,而别的值秋毫无犯,这是和save非常显著的区别,save()时候如果不传入完整数据,那么没有传入的数据就会被schema中默认值替代!
恩,关于更新,就是这么多了,更多例子就不补充了。继续删除。
关于删除
类似更新,它有很类似的方法:
- remove()
- findOneRemove()
- findByIdAndRemove()
remove貌似不用再作介绍了,在之前笔记有过若干例子。
这里说说后面两个方法,他们接受相同的参数:
- Query Object 查询对象 输入对象进行匹配和删除
- Options 一个对象,接受两个属性:
sort
(对匹配文档排序)和select
(设置返回给callback的对象的属性) - Callback 一个回调函数,好像无需说更多
总结
就这样吧,虽然还是不是很详细,但是作为一份笔记和总结来说,这已经足够。mongoose的中文资料不多,深入的更少,这里就仅仅就CURD进了相对深入的记录,聊做记忆强化和备忘。