在Bookshelf.js中使用`withRelated`时指定备用`id`

时间:2016-05-13 23:43:40

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

我很好奇是否有办法更改模型上指定id时使用的withRelated

情况如下:

我正在开发一个具有日历组件的平台,该日历需要支持定期约会。我不是创建定期约会的每个潜在实例,而是动态地生成这些重复,这导致更少的维护。我的Appointment模型也具有与每个实例关联的关系。 Appointment可以包含许多services等。当使用withRelated在数据库中存在的约会(不是动态生成)上加载这些关系时,id约会被传递到withRelated尝试加载和工作的任何关系。

但是,使用这些动态生成的约会,我实际上需要使用生成这些实例的父约会的id来加载关系。不幸的是,我似乎无法找到一种方法来指定使用父id或我可以拦截的地方并在加载关系之前更改它。

我的情况很奇怪,但如果我可以更改调用withRelated时传入的内容,那将是一个简单的修复。

这可能吗?

我也愿意接受其他建议。

目标/期望结果

为了清楚起见,我的目标非常简单。当Bookshelf加载多对多关系时,它使用加入模型的idAttribute来加载相关关系。

例如,Appointment是我的主要模型,与Pets具有多对多关系。因此,当我加载pets关系时,Bookshelf会在appointment_pets表上进行联接,以查找appointment_pet.appointment_id IN (?)的所有记录,其中参数为id来自{{1}表格。

我希望的目标是在查找这些关系时能够用appointment替换appointment.id,因为在我的情况下,这些动态记录实际上并不存在于数据库中,因此需要使用附加到父记录的信息,确实存在。

更新

我终于能够通过暂时将模型上的appointment.parent_idid更改为idAttribute,将不同的id注入上述查询中。查询是正确的,传递的参数也是正确的,但返回模型时关系为空。

parent_id

我看到以下调试输出:

// appointment model

    pets() {

        return this.belongsToMany('Pet', 'appointment_pet', 'parent_id');
    },
},

// Returns all appointments
    fetchAll(businessId, options) {

        options = options || {};

        // If a start and end date are passed, return all appointments
        // within that range, with recurrences expanded.
        if (!_.isUndefined(options.startDate) &&
            !_.isUndefined(options.endDate)) {

            const startDate = Moment(options.startDate);
            const endDate = Moment(options.endDate);

            // temporarily change id attribute so `parent_id` is used when looking up the relation
            Appointment.prototype.idAttribute = 'parent_id';

            return Appointment
                .query((qb) => {

                    qb.from(Bookshelf.knex.raw('get_appointments(?, ?, ?) AS appointment', [businessId, startDate.toISOString(), endDate.toISOString()]));
                })
                .fetchAll({
                    withRelated: [{
                        pets: (qb) => {
                            qb.select(['appointment_id as parent_id', 'pet.*']);
                        }
                    }]
                });
        }

        // Otherwise, return all appointments
        return Appointment.findAll({ businessId: businessId }, options);
    },

在postgres中运行此命令,我看到正确的输出,但仍然没有关系。我看到#1203并尝试将{ method: 'select', options: {}, bindings: [ null, '35a2941c-d73f-4cf3-87de-bfbcbc92fbc5', <-- these are all `appointment.parent_id` '5de28a57-ce4c-4fcc-865a-54cf97e08c6c', 'bf4b6784-b96a-4321-8335-e449aa8dcda1', '695edc54-3a93-42a5-a3e0-b331f26912cf', '76a99204-9659-4270-904c-2c42e5c40a15', '28437e3c-abc1-4fd6-8c26-5543c09ab730', '350da29d-0e82-4e6c-b9fe-be31c64655b4', 'bcaee041-c9ec-4a34-8c0d-8f21d2d79197', '91380fcc-2f0d-4344-a24b-dc37abe3931f', '31796797-5041-4fae-815b-0f2c368654b0', '94800af3-fd23-4b59-af88-15b1f622e8e1', 'aa8c202d-249e-4ffc-ab55-e535f2c2121f', '8a1fd093-45a6-4864-8c52-ea8851740f77', '5f91ad6f-4231-4d18-b718-d99fcc17a18b', '5f879e43-a44f-41dd-b9dd-11f06af4cc8d' ], sql: 'select "pet".*, "appointment_pet"."parent_id" as "_pivot_parent_id", "appointment_pet"."pet_id" as "_pivot_pet_id" from "pet" inner join "appointment_pet" on "appointment_pet"."pet_id" = "pet"."id" where "appointment_pet"."parent_id" in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'} 明确添加到选择中,但仍然没有运气。

1 个答案:

答案 0 :(得分:0)

很遗憾,我没有足够的数据来复制您的问题。我在一个基本的一对多示例上尝试过,我认为最简单的方法是在模型本身中定义一个新的关系。 E.g:

var Genre = bookshelf.Model.extend({
    tableName: 'genres',
    movie: function() {
        return this.hasMany(Movie);
    },
    movie_parent: function() {
        return this.hasMany(Movie, 'parent_id');
    }
});

var Movie = bookshelf.Model.extend({
    tableName: 'movies'
    genre: function() {
        return this.belongsTo(Genre);
    },  
    genre_parent: function() {
        return this.belongsTo(Genre, 'id');
    }

});

那么,你可以在withRelated属性中查询它相当简单。

new Movie().fetchAll({
    withRelated: ['genre_parent'] //can be replaced with withRelated: ['genre']
}).then(function(movies) {
    res.json(movies);

});

如果这不是您正在寻找的解决方案,请提供其他数据(数据库结构会很有趣)