【问题标题】:Always fetch from related models in Bookshelf.js始终从 Bookshelf.js 中的相关模型中获取
【发布时间】:2016-02-28 07:21:02
【问题描述】:

我希望baffle.where({id: 1}).fetch() 始终将typeName 属性作为baffle 模型的一部分,而不是每次都明确地从baffleType 获取它。

以下内容对我有用,但如果baffle 模型是直接获取的,而不是通过关系,似乎withRelated 将加载关系:

let baffle = bookshelf.Model.extend({
    constructor: function() {
        bookshelf.Model.apply(this, arguments);

        this.on('fetching', function(model, attrs, options) {
            options.withRelated = options.withRelated || [];
            options.withRelated.push('type');           
        });
    },

    virtuals: {
        typeName: {
            get: function () {
                return this.related('type').attributes.typeName;
            }
        }
    },
    type: function () {
        return this.belongsTo(baffleType, 'type_id');
    }
});

let baffleType = bookshelf.Model.extend({});

这样做的正确方法是什么?

【问题讨论】:

    标签: node.js bookshelf.js knex.js


    【解决方案1】:

    回购问题与Fetched事件有关,但是Fetching事件工作正常(v0.9.2)

    例如,如果您有第三个模型,例如

    var Test = Bookshelf.model.extend({
       tableName : 'test',
       baffleField : function(){
           return this.belongsTo(baffle)
       } 
    })
    

    然后执行Test.forge().fetch({ withRelated : ['baffleField']}), fetching 挡板上的事件将触发。但是ORM 不会包含type(子相关模型),除非您通过

    明确告诉它这样做
    Test.forge().fetch({ withRelated : ['baffleField.type']})
    

    但是,如果它正在为N records 制作N Query,我会try to avoid

    更新 1

    我说的是你在 fetching 事件中所做的同样的事情,比如

    fetch: function fetch(options) {
       var options = options || {}
       options.withRelated = options.withRelated || [];
       options.withRelated.push('type');    
        // Fetch uses all set attributes.
       return this._doFetch(this.attributes, options);
    }
    

    model.extend。但是,如您所见,这可能会在 version 更改时失败。

    【讨论】:

    • fetching 的好点子,谢谢。那么,如果我想保持业务逻辑干燥并跳过所有fetch() 调用中的{ withRelated: ... } 部分,那么修改options.withRelated 是唯一的选择吗?在应用的这一部分中,性能并不重要。
    • @estus 我认为是的。但是我一直在使用 sequelize,所以不能确定。做同样事情的另一种方法是overriding(对 JS 来说不是一个好词)model.extend 中的 fetch 方法。然而,使用fetching 事件更像是一种书架式的方式。覆盖方法是一种更简洁的方法,但它可能会在版本升级/降级时失败。
    • 看起来fetching被触发了,但是当'baffle'作为关系加载时没有加载嵌套关系,所以应该在每个父模型中指定fetching。您能否为覆盖fetch 添加一个示例?应该是 fetch: function (...args) { return bookshelf.Model.prototype.fetch.bind(this)(...args) } 之类的吗?
    • 谢谢,看起来不错,我想这就是_doFetch 存在的原因。
    【解决方案2】:

    这个问题太老了,但我还是要回答。

    我通过添加一个新函数fetchFull 解决了这个问题,它可以让事情保持干爽。

    let MyBaseModel = bookshelf.Model.extend({
      fetchFull: function() {
        let args;
        if (this.constructor.withRelated) {
          args = {withRelated: this.constructor.withRelated};
        }
        return this.fetch(args);
      },
    };
    
    let MyModel = MyBaseModel.extend({
        tableName: 'whatever',
      }, {
        withRelated: [
          'relation1',
          'relation1.related2'
        ]
      }
    );
    

    然后,无论何时查询,您都可以调用Model.fetchFull() 来加载所有内容,或者如果您不想影响性能,您仍然可以求助于Model.fetch()

    【讨论】:

    • 谢谢,永远不会太晚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多