Objection.js急切的多对多关系问题

Objection.js eager many-to-many relationship problems

每当尝试使用预先加载获取 Objection.js 中的用户组时,我都会收到以下错误:

错误

TypeError: Cannot read property 'size' of null
    at findRelationPropsToSelect (/vagrant/node_modules/objection/lib/queryBuilder/operations/eager/WhereInEagerOperation.js:184:36)
    at WhereInEagerOperation.onBuild (/vagrant/node_modules/objection/lib/queryBuilder/operations/eager/WhereInEagerOperation.js:35:48)
    at QueryBuilder.callOperationMethod (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:353:33)
    at forEachOperation.op (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:449:14)
    at QueryBuilder.forEachOperation (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:287:13)
    at QueryBuilder.executeOnBuild (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:447:10)
    at QueryBuilder.buildInto (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:440:10)
    at buildInto (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilder.js:1361:25)
    at doExecute (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilder.js:1265:23)
    at Bluebird.try.then (/vagrant/node_modules/objection/lib/queryBuilder/QueryBuilder.js:583:19)
    at tryCatcher (/vagrant/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/vagrant/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/vagrant/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/vagrant/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/vagrant/node_modules/bluebird/js/release/promise.js:694:18)
    at _drainQueueStep (/vagrant/node_modules/bluebird/js/release/async.js:138:12)

我的迁移和种子都是 运行 正确的,当我通过 PSequel 连接时可以看到它们。我一定是在做一些愚蠢的事情,但作为 Objection.js 的新手,我看不到它。

型号

我的模型如下:

// models/base.model.js
import { Model } from 'objection';

export class BaseModel extends Model {
    static modelPaths = [__dirname];
}

// models/user.model.js
import { Model } from 'objection';

import { BaseModel } from './base.model'

export class User extends BaseModel {
    static tableName = 'users';

    static relationMappings = {
        groups: {
            relation: Model.ManyToManyRelation,
            join: {
                from: 'users.id',
                through: {
                    from: 'users_groups.user_id',
                    to:   'users_groups.group_id'
                },
                to: 'groups.id'
            }
        }
    }
}

// models/group.model.js
import { Model } from 'objection';

import { BaseModel } from './base.model';

export class Group extends BaseModel {
    static tableName = 'groups';

    static relationMappings = {
        users: {
            relation: Model.ManyToManyRelation,
            join: {
                from: 'groups.id',
                through: {
                    from: 'users_groups.user_id',
                    to:   'users_groups.group_id'
                },
                to: 'users.id',
            }
        }
    }
}

迁移

我的迁移如下:

// migrations/20190307214041-create-users-table.js
exports.up = function(knex) {
    return knex.schema
        .createTable('users', function(table) {
            table.increments('id').primary();
            table.string('firstName').notNullable();
            table.string('lastName').notNullable();
            table.string('avatar').nullable();
            table.string('email').notNullable();
            table.string('password').notNullable();
            table.integer('active').notNullable().defaultTo(0);
            table.timestamps();

            table.unique('email');
        });
};
exports.down = function(knex) {
    return knex.schema
        .dropTable('users');
};

// migrations/20190307214814-create-groups-table.js
exports.up = function(knex) {
    return knex.schema
        .createTable('groups', function(table) {
            table.increments('id').primary();
            table.string('name');
            table.integer('active');
            table.timestamps();
        });
};
exports.down = function(knex) {
    return knex.schema
        .dropTable('groups');
};

// migrations/20190307220010-create-groups_users-table.js
exports.up = function(knex) {
    return knex.schema
        .createTable('users_groups', function(table) {
            // table.increments('id').primary();
            table.integer('user_id');
            table.integer('group_id');
            // table.integer('users_id').references('users.id');
            // table.integer('groups_id').references('groups.id');
        });
};
exports.down = function(knex) {
    return knex.schema
        .dropTable('users_groups');
};

查询示例

工作查询[=​​37=]

此查询工作正常,我取回了数据。

try {
    const users = await User.query().orderBy('id');

    res.status(200).json(users);
} catch (err) {
    console.error(err);
    res.status(500).json({ message: 'There was an error' });
}

查询失败

这个查询失败了,我得到了这个问题顶部显示的错误。

try {
    const user = await User.query()
        .where('id', Number(req.params.id))
        .eager('groups');

    res.status(200).json(user);
} catch (err) {
    console.error(err);
    res.status(500).json({ message: 'There was an error' });
}

原来是babel配置问题。

当我将代码更改为如下所示时,它起作用了:

import path from 'path';
import { Model } from 'objection';

import { BaseModel } from './base.model';

export class Group extends BaseModel {
    static get tableName() {
        return 'groups';
    }

    static get relationMappings() {
        return {
            users: {
                modelClass: path.join(__dirname, 'user.model'),
                relation: Model.ManyToManyRelation,
                join: {
                    from: 'groups.id',
                    through: {
                        from: 'users_groups.group_id',
                        to: 'users_groups.user_id'
                    },
                    to: 'users.id',
                }
            }
        };
    }
}

import path from 'path';
import { Model } from 'objection';

import { BaseModel } from './base.model'

export class User extends BaseModel {
    static get tableName() {
        return 'users';
    }

    static get relationMappings() {
        return {
            groups: {
                modelClass: path.join(__dirname, 'group.model'),
                relation: Model.ManyToManyRelation,
                join: {
                    from: 'users.id',
                    through: {
                        from: 'users_groups.user_id',
                        to:   'users_groups.group_id'
                    },
                    to: 'groups.id'
                }
            }
        };
    }
}