2015-11-05 74 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']; 
}); 

,並在多個地方使用它,或有不同版本的白名單,都在模型層管理。