mongoose 中toJSON 函数的妙用

最近需求方提出了一个比较头疼的需求,导致了一些性能问题,最终查了很多资料才找到一个比较好的解决方案。

情况是这样的,在一个需求中,每个用户是可以有几个邀请码的,可以邀请别人注册,在用户界面可以看到自己的邀请码,管理员在后台也可以查看和管理。一天管理员心血来潮,让给他生成三万个邀请码,问题不大,就用脚本给他生成了,结果生成之后,出现了性能问题。首先是接口返回的用户对象,大小变成了100k左右,另外,设涉及邀请码渲染的页面,基本也是点开就卡死了。

数据库采用的是mongo数据库,用户信息大概存成这样:

{
    name:'xxx',
    codes:['123']
}

原来运行的好好的,就因为一个人要在codes字段里添加三万个邀请码,导致了数据量巨大。这个问题还不太好改,因为之前的很多接口设计,都是用户信息如果有变更,就返回新的用户数。带来的问题就是,涉及返回userinfo 的接口很多。

为了兼容这个个例,我能想到的办法就是,判断是不是管理员,是的话,codes 字段就只返50个,截断返回。想法是好的,但是实际操作起来,全文一搜索,user.find() 这个函数,得用了几十处,难道一个一个的改吗?专门写一个截断函数,去包一下user.find() 这个函数?我内心是拒绝的,并且很麻烦,还会造成维护的困难,将来如果完了用这个包装函数,可能就产生bug 了。

Mongoose 能不能在查询出结果的时候,统一做一些事情呢?这样的话,user.find()就可以不用改了?顺着这个思路,开始查起了资料。

最开始查到了get/set ,我可以定义应该getter ,遇到admin ,就只返回50条数据呀,是不是很完美?但是其他问题跟着来了。有一个逻辑,当用户注册的时候,会判断这个用户是不是你邀请的,那这个时候,其实是要取出codes 字段,执行一些codes.includes(code)的。如果定义了这样的getter,只返回50个邀请码,那很可能是你邀请的用户,但是代码判断为fasle,这不bug了嘛。

其实我要的效果,是在服务端处理的时候,还是正常处理,只是在返回到前端的时候,截断这种异常数据。难道只能一个接口一个接口去改写吗?拒绝!

经过一晚上的熬夜查资料,终于找到了一个理想的函数。

toJSON

toJSON(optons)函数可以设置选项,其中有一个options.transform

[options.transform=null] «Function|null» if set, mongoose will call this function to allow you to transform the returned object

mongoose 在把一个doc 转换为json 的时候,会调用一下这个函数,说白了,可以在转json 之前做一些处理。这个函数神奇在上面地方呢?doc 在其他场景下,包括在内存中的读写等,调用的都是toObject()函数,只有在返回http 的response 的时候,才会调用toJSON 函数,简直完美符合我的需求呀,赶紧试下,完美!

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注