开发者问题收集

Objection JS & Postgres 和 Express 在多对多关系查询中返回“TypeError:无法读取 null 的属性‘isPartial’”

2020-06-07
1495

我试图将名为“products”的表与另一个名为“tags”的表关联起来。 我有一个名为“products_tags”的多对多表。

运行 const product = await Product.relatedQuery('tags').findById(1); 时,我收到以下错误:

TypeError: Cannot read property 'isPartial' of null
    at findFirstNonPartialAncestorQuery (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:194:18)
    at Function.createParentReference (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\relations\RelationOwner.js:24:48)
    at QueryBuilder._findOperationFactory (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\model\Model.js:819:25)
    at addFindOperation (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1551:31)
    at addImplicitOperations (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1539:5)
    at beforeExecute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:1439:13)
    at QueryBuilder.execute (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:681:13)
    at QueryBuilder.then (C:\Users\AmazeCPK\Documents\_Web\fractal-insight2\node_modules\objection\lib\queryBuilder\QueryBuilder.js:634:26)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

我的产品型号:

const {Model} = require('objection');

class Product extends Model {
    static get tableName() {
        return 'products'
    }

    static get relationMappings() {
        const Tag = require('./Tag');

        return {
            tags: {
                relation: Model.ManyToManyRelation,
                modelClass: Tag,
                join: {
                    from: 'products.id',
                    through: {
                        from: 'products_tags.product_id',
                        to: 'products_tags.tag_id'
                    },
                    to: 'tags.id'
                }
            }
        }
    }
}

module.exports = Product;

Tags.js

const { Model } = require('objection');

class Tag extends Model {
    static get tableName() {
        return 'tags';
    }

    static get relationMappings() {
        const Product = require ('./Product');

        return {
            products: {
                relation: Model.ManyToManyRelation,
                modelClass: Product,
                join: {
                    from: 'tags.id',
                    through: {
                        from: 'products_tags.tag_id',
                        to: 'products_tags.product_id'
                    },
                    to: 'products.id'
                }
            }
        }
    }
}

module.exports = Tag;

我已确保表名和关系正确,并确保数据库中有匹配的数据。非常感谢您的帮助。谢谢。

编辑:这是迁移设置

//...
        knex.schema.createTable('tags', table => {
            table.increments('id').notNullable();
            table.text("name");
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),
        knex.schema.createTable('products', table => {
            table.increments('id').notNullable();
            table.text("name");
            table.text("description");
            table.float("price");
            table.integer('category_id').references('id').inTable('categories');
            table.boolean("can_be_personalized").defaultTo(false);
            table.specificType('images', 'text ARRAY');
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),
        knex.schema.createTable('products_tags', table => {
            table.increments('id').notNullable();
            table.integer('product_id').references('id').inTable('products');
            table.integer('tag_id').references('id').inTable('tags');
            table.boolean("is_deleted").defaultTo(false);
            table.timestamps(true, true);
        }),
2个回答

您肯定不再需要解决方案了,但对于未来的读者来说,有三件事可能会导致这种情况。我刚刚花了两个半小时调试这个相同的错误,因此从最容易验证到最难验证的顺序为:

  1. 您没有为相关查询的父模型指定主 ID。 如果您使用的是 ModelB.relatedQuery('modelARelation') ,那么您还必须调用 .for(modelBId) ,否则您将收到此错误。(这是我遇到的情况,因为我混淆了 req.queryreq.params :facepalm:)
ModelB.relatedQuery('modelARelation'); // when run alone, you get this answer

...

const modelBId = req.query.modelBId;
ModelB.relatedQuery('modelARelation').for(modelBId); // works just fine as long as modelBId is properly defined.
  1. 需要循环 循环依赖循环。如果 ModelA 与 ModelB 相关,且 ModelB 与 ModelA 相关,请确保您使用的是文档中概述的 循环依赖策略 之一。
  2. 拼写错误 。我不想这么说,但如果你已经走到这一步,几乎可以肯定你在某个地方有拼写错误。去吃点东西或让别人看看。这实际上只是一般的好建议。
TheHiggsBroson
2022-03-04

以我有限的经验来看,此错误通常发生在由于某种原因无法创建对象时。通常这是导出问题或构造函数问题。

您确定文件名正确吗?您将其命名为 Tags.js ,但您的 const Tag = require('./Tag');

user6269972
2020-06-13