2015-11-05 80 views
0

我正在尝试为包含虚拟字段的REST API生成精简记录。Keystone.js/mongoose虚拟字段精简记录

如何实现虚拟域的猫鼬的官方文档:
http://mongoosejs.com/docs/guide.html

我的模型:

var keystone = require('keystone') 
    , Types = keystone.Field.Types 
    , list = new keystone.List('Vendors'); 

list.add({ 
    name : { 
      first: {type : Types.Text} 
     , last: {type : Types.Text} 
    } 
}); 

list.schema.virtual('name.full').get(function() { 
    return this.name.first + ' ' + this.name.last; 
}); 

list.register(); 

现在,让我们来查询模型:

var keystone = require('keystone'), 
    vendors = keystone.list('Vendors'); 

vendors.model.find() 
    .exec(function(err, doc){ 
     console.log(doc) 
    }); 

虚拟字段名.full不在这里:

[ { _id: 563acf280f2b2dfd4f59bcf3, 
    __v: 0, 
    name: { first: 'Walter', last: 'White' } }] 

但是,如果我们这样做:

vendors.model.find() 
    .exec(function(err, doc){ 
     console.log(doc.name.full); // "Walter White" 
    }); 

那么虚拟所示。

我想原因是,当我做一个console.log(文档)的Mongoose document.toString()方法被调用,它不包括虚拟默认情况下。很公平。这是可以理解的。

要包含虚函数在任何的转换方法,你必须去:

doc.toString({virtuals: true}) 
doc.toObject({virtuals: true}) 
doc.toJSON({virtuals: true}) 

然而,这包括键我不希望我的REST API泵出我的用户:

{ _id: 563acf280f2b2dfd4f59bcf3, 
    __v: 0, 
    name: { first: 'Walter', last: 'White', full: 'Walter White' }, 
    _: { name: { last: [Object], first: [Object] } }, 
    list: 
    List { 
    options: 
     { schema: [Object], 
     noedit: false, 
     nocreate: false, 
     nodelete: false, 
     autocreate: false, 
     sortable: false, 
     hidden: false, 
     track: false, 
     inherits: false, 
     searchFields: '__name__', 
     defaultSort: '__default__', 
     defaultColumns: '__name__', 
     label: 'Vendors' }, 
    key: 'Vendors', 
    path: 'vendors', 
    schema: 
     Schema { 
     paths: [Object], 
     subpaths: {}, 
     virtuals: [Object], 
     nested: [Object], 
     inherits: {}, 
     callQueue: [], 
     _indexes: [], 
     methods: [Object], 
     statics: {}, 
     tree: [Object], 
     _requiredpaths: [], 
     discriminatorMapping: undefined, 
     _indexedpaths: undefined, 
     options: [Object] }, 
    schemaFields: [ [Object] ], 
    uiElements: [ [Object], [Object] ], 
    underscoreMethods: { name: [Object] }, 
    fields: { 'name.first': [Object], 'name.last': [Object] }, 
    fieldTypes: { text: true }, 
    relationships: {}, 
    mappings: 
     { name: null, 
     createdBy: null, 
     createdOn: null, 
     modifiedBy: null, 
     modifiedOn: null }, 
    model: 
     { [Function: model] 
     base: [Object], 
     modelName: 'Vendors', 
     model: [Function: model], 
     db: [Object], 
     discriminators: undefined, 
     schema: [Object], 
     options: undefined, 
     collection: [Object] } }, 
    id: '563acf280f2b2dfd4f59bcf3' } 

我可以随时当然只是删除不需要的钥匙,但是这似乎并不完全正确:

vendors.model.findOne() 
    .exec(function(err, doc){ 
     var c = doc.toObject({virtuals: true}); 
     delete c.list; 
     delete c._; 
     console.log(c) 
    }); 

这产生了我需要的东西:

{ _id: 563acf280f2b2dfd4f59bcf3, 
    __v: 0, 
    name: { first: 'Walter', last: 'White', full: 'Walter White' }, 
    id: '563acf280f2b2dfd4f59bcf3' } 

是否没有更好的方式获得精益记录?

回答

1

我想你想的select方法..这样的事情:

vendors.model.findOne() 
.select('_id __v name'). 
.exec(function(err, doc){ 
    console.log(c) 
}); 

而且我个人更喜欢的模式,而不是在原稿设置virtuals: true,而是取决于使用情况下,我猜。

+0

我认为你是对的,而我不想要的字段是属于Keystone js的内部字段。如果我运行本地Mongo DB或Mongoose,则不会在结果集中包含.list和._字段。 – ChrisRich

0

一个解决方案是使用一个模块像Lodash(或下划线),它允许你pick属性名称的白名单:

vendors.model.findOne() 
    .exec(function(err, doc){ 
     var c = _.pick(doc, ['id', 'name.first', 'name.last', 'name.full']); 
     console.log(c) 
    }); 

鉴于通过REST API服务这个数据您的使用情况,我想明确定义属性名称的白名单更安全。你甚至可以定义你的架构中的虚拟财产,它返回预定义的白名单:

list.schema.virtual('whitelist').get(function() { 
    return ['id', 'name.first', 'name.last', 'name.full']; 
}); 

,并在多个地方使用它,或有不同版本的白名单,都在模型层管理。