关于mongoose查询结果遇到的疑问,virtual属性的用法
发布于 3天前 作者 jerrywu55 217 次浏览 来自 问答

我对话题模型Topic定义了total_pv 字段 ,

然后还有一个pv virtual 属性,

pv = total_pv * 10;

 Topic.find({},function(err,topics){
 });
  • 如果我直接将topics返回给客户端,json里面不存在我想要的pv字段。

      return res.json({code:200,msg:'ok',topics:topics});
    
  • 并且我不想返回total_pv字段给客户端,只能用forEach 遍历topics 删除total_pv吗?

  • 查询返回的是一个docs,我动态修改他的属性没有效果。

     topics.forEach(function(topic){
            topic.pv = topic.total_pv * 10;
    });

期待大家帮忙解惑,O(∩_∩)O谢谢!

14 回复

刚查了下mongoose API 文档

// path, value
doc.set(path, value)

// object
doc.set({
    path  : value
  , path2 : {
       path  : value
    }
})

// on-the-fly cast to number
doc.set(path, value, Number)

// on-the-fly cast to string
doc.set(path, value, String)

// changing strict mode behavior
doc.set(path, value, { strict: false });

然道是不能用 . 表达式赋值 而是要用 set 方法来赋值。。

个人见解: 第一个的话,total_pv * 10; 有放在YourSchema.virtual(“pv”).get()方法里面么?

第二个问题的话,可以通过在回调函数前增加一个option字段参数解决,如mongoose API中的例子:

// name LIKE john and only selecting the "name" and "friends" fields, executing immediately 
MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { });

@DavidCai1993 又查了下文档,好像 移除total_pv 字段可以像下面这样用

// specify the transform schema option
if (!schema.options.toObject) schema.options.toObject = {};
schema.options.toObject.transform = function (doc, ret, options) {
  // remove the _id of every document before returning the result
  delete ret._id;
}

// without the transformation in the schema
doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }

// with the transformation
doc.toObject(); // { name: 'Wreck-it Ralph' }

@DavidCai1993 pv 字段我有在Schema设置virtual getter

@DavidCai1993

    MyModel.find({ name: /john/i }, 'name friends’, function (err, docs) { })

选择的字段里面如果没有total_pv 的话,不知道 虚属性 pv 会不会生效

@jerrywu55 1,getter里已经设置了也return出来了取不到就奇怪咯 - -||| 2,的确哦,不过既然虚属性已经定义在schema里,试试选择的字段里加上虚属性而不加 total_pv?

@DavidCai1993 我试过选择的字段直接写pv 而不写 total_pv ,结果没有pv这个字段。

我的理解是,虚属性是查询数据库返回后,mongoose 再根据我们之前的定义加上的。

所以要选择total_pv ,然后我根据下面的用法来删除total_pv字段。

// specify the transform schema option
if (!schema.options.toObject) schema.options.toObject = {};
schema.options.toObject.transform = function (doc, ret, options) {
  // remove the _id of every document before returning the result
  delete ret._id;
}

现在还剩一个疑问就是 将topics 返回给客户端时,没有序列化pv 这个虚属性。

@DavidCai1993 刚才又看了下文档,好像document 对象的toJSON和toObject方法里面 默认将virtual 属性排除了。

文档说需要对Schama做下面的配置,应该就能再 我们将document 转换成JSON时去序列化virtual属性

    schema.set('toJSON', { virtuals: true })
    
    schema.set('toObject', { virtuals: true })
    
    或
    
    doc.toObject({ getters: true, virtuals: true })

谢谢你啦!上班后我去调试一下

@jerrywu55 翻了翻 mongoose文档,发现了这一段:

Note that if the resulting record is converted to an object or JSON, virtuals are not included by default. Pass virtuals : true to either toObject() or to toJSON() to have them returned.

@jerrywu55 哈哈,我们正好前后脚都发现了这个

@DavidCai1993 嗯嗯,我刚才查文档的时候也注意到了, 非常感谢!

今天去公司将上面的理论 实践了下, 确实可行。 实现了我的需求,哈哈。

pv= total_pv * 10

我好像明白了什么 : )

回到顶部