关于mongoose踩到的一个小坑
发布于 9 年前 作者 luoyjx 5422 次浏览 最后一次编辑是 8 年前 来自 问答

mongoose大家应该都用过。 而有两个细节不知道大家遇到过没。

Model的toObject方法

这个方法会将你模型中的数据转换为一个一般的javascript对象。 当时为什么会用到这个方法? 这样的,当时我为了将首页的列表数据,暂时缓存在redis中。于是查询出来之后,包括作者和回复信息,添加到这个模型上,再存入redis的。 问题就出现了,发现取出来之后的对象没有了作者及回复信息,于是看了看mongoose的文档之后,貌似是存入之前将model转换成一个普通对象,并且把Schema中没有的属性都给丢弃了。 后来我是这么弄的,查询到Topic先用toObject转成普通对象,再追加属性,缓存之后就不会出现上面的问题了。

Schema的virtual方法

一个是Schema中的virtual方法,恩给个例子看看,社区的Topic的Model中用于在查询时额外附加一个中文的板块名的属性:

TopicSchema.virtual('tabName').get(function () {
  var tab  = this.tab;
  var pair = _.find(config.tabs, function (_pair) {
    return _pair[0] === tab;
  });

  if (pair) {
    return pair[1];
  } else {
    return '';
  }
});

这是在模型中添加的一个属性,在上面的问题使用toObject()时,那么这个virtual属性就给丢了。 于是现在把toObject去掉,列表不缓存到redis。

问题

  1. 如果需要缓存到redis且需要virtual属性,可行么?
  2. 大家有没有类似的经历分享下的
8 回复

1)虚拟属性只是在mongoose对象上挂的函数而已,不调用,不会返回结果,无法像实体字段一般可以在toObject之后还能保留下来 2)并且虚拟i属性也不能像实体字段那样拿来建立索引并用于查询

如果想在toObject之后还能保留有虚拟属性,能想到的只有在toObject之前加一层处理逻辑,将虚拟属性保留下来

如果想将一个虚拟字段用来参加建立索引,只能把这个虚拟属性定义为实体字段了,且依然要考虑那些没有此字段的老数据。

这样, 就能在序列号的时候保存下来了

@TossShinHwa 你写的这个库不错啊, 挺有用的样子

@TossShinHwa 非virtual的,手动添加的属性应该就不行了吧

@macross2005 序列号->序列化. 有兴趣可以试试:) 相关文档 http://tossshinhwa.github.io/node-odata/cn/

@luoyjx 当然, 无论怎样, 都要在 schema 里面声明才行的.

listSchema.set('toObject', {getters: true, virtuals: true}); listSchema.set('toJSON', {getters: true, virtuals: true}); 像上面这样,可以设置在toObject和toJSON时对于getters和vitruals属性的操作。 不过我这边具体在用的时候,还是,手动的重新复制一份。。。

@jzlikewei 因为我之前是在做手动联查,于是后来用populate(),发现查询次数也是差不多的

回到顶部