簡體   English   中英

Keystone.js /貓鼬虛擬字段精益記錄

[英]Keystone.js / mongoose virtual fields lean record

我正在嘗試為包含虛擬字段的REST API生成精益記錄。

有關如何為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)
    });

虛擬字段name.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(doc)時,會調用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' }

有沒有更好的方法來獲得精簡記錄?

我認為您想要select方法..類似這樣的東西:

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

我個人也更喜歡設置virtuals: true而不是文檔上的schema,但是取決於我猜想的用例。

一種解決方案是使用類似Lodash (或Underscore )的模塊,該模塊允許您選擇屬性名稱的白名單:

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'];
});

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM