Sequelize findOne错误:TypeError indexOf undefined

时间:2017-08-18 14:11:29

标签: javascript node.js sequelize.js

第一次使用sequelize与新数据库一起工作,通过cli完成表创建和迁移(我们使用遗留数据库模式,使用它来构建与现有表匹配的模型没有问题,所以我熟悉基本用法)。当我尝试针对其中一个新表测试查询时,我得到了一个类型错误。

系统:Sequelize v4.5.0,Node v8.1.4,npm v5.3.0

首先是Stacktrace:

TypeError: Cannot read property 'indexOf' of undefined
    at attributes.map.attr (**PATH**/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1222:27)
    at Array.map (native)
    at Object.escapeAttributes (**PATH**/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1207:37)
    at Object.selectQuery (**PATH**/node_modules/sequelize/lib/dialects/abstract/query-generator.js:979:28)
    at QueryInterface.select (**PATH**/node_modules/sequelize/lib/query-interface.js:672:27)
    at Promise.try.then.then.then (**PATH**/node_modules/sequelize/lib/model.js:1539:34)
    at tryCatcher (**PATH**/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (**PATH**/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (**PATH**/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (**PATH**/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (**PATH**/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (**PATH**/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (**PATH**/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (**PATH**/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:7

代码本身是一个相当简单的连接测试。注入依赖项并尝试查询。

查询代码:

#!/usr/bin/env node
'use-strict';

const errorMessage = require('../../../util/error-msg');

class Sync {
  constructor(db, log) {
    this.db = db;
    this.log = log;
  }

  async getBatch() {
    try {
      let result =  await this.db.ShopifyPriceRule.findOne({where: {id: 1}});

      return result;
    } catch (error) {
      let msg = errorMessage(error, 'Sync.getBatch');
      this.log.error({ error: msg }, error.message);
    }
  }
}

module.exports = Sync;

连接:

#!/usr/bin/env node
'use-strict';

const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');

module.exports = function makeConnection(env, log, dir, indexFile) {
  let db = {};

  try {
    env.logging = msg => log.trace({sequelize: msg});
    let sequelize = new Sequelize(env);

    fs.readdirSync(dir)
      .filter(file => ((file.indexOf('.') !== 0) && (file !== indexFile) && (file.slice(-3) === '.js')))
      .forEach(key => {
        const model = sequelize.import(path.join(dir, key));
        db[model.name] = model;
      });

    Object.keys(db).forEach(modelName => {
      if (db[modelName].associate) {
        db[modelName].associate(db);
      }
    })

    sequelize.authenticate()
      .then(() => log.info('DB Connection has been established to Schema.'))
      .catch(err => log.error({ err: err }, 'Unable to connect with DB'));


    db.sequelize = sequelize;
    db.Sequelize = Sequelize;

    return db;
  } catch (error) {
    log.error({error: error});
  }
}

模型

'use strict';
module.exports = function(sequelize, DataTypes) {
  var ShopifyPriceRule = sequelize.define('ShopifyPriceRule', {
    channel_id: DataTypes.STRING,
    promo_id: DataTypes.INTEGER,
    title: DataTypes.STRING,
    target_type: DataTypes.STRING,
    target_selection: DataTypes.STRING,
    allocation_method:DataTypes.STRING,
    once_per_customer: DataTypes.BOOLEAN,
    customer_selection: DataTypes.STRING,
    entitled_product_ids: DataTypes.JSON,
    entitled_variant_ids: DataTypes.JSON,
    entitled_collection_ids: DataTypes.JSON,
    entitled_country_ids: DataTypes.JSON,
    prerequisite_saved_search_ids: DataTypes.JSON,
    prerequisite_subtotal_range: DataTypes.JSON,
    prerequisite_shipping_price_range: DataTypes.JSON
  });

  ShopifyPriceRule.associate = models => {
    ShopifyPriceRule.belongsTo(models.Promo)
  };

  return ShopifyPriceRule;
};

我尝试了什么

  • 阅读所有关于SO的类似问题
  • 阅读Sequelize' github问题页面中的类似问题
  • 尝试连接到同一架构中的另一个表
  • 尝试在其他列上进行选择(以防不在模型中的默认ID字段是问题)
  • 同一桌上的原始查询,按预期工作

我在这里忽略了一些超级基本的东西是积极的,但我无法看到它。

1 个答案:

答案 0 :(得分:0)

回到一个工作示例,事实证明我开始使用Sequelize,而他们仍在更新文档以明确4.x带来的变化。此外,CLI仍在使用旧格式来自动构建模型。对我而言(关于清晰度)的关键是ES6类结构并自己编写模型。

模型

#!/usr/bin/env node
'use-strict';

const Sequelize = require('sequelize')

class ShopifyPriceRule extends Sequelize.Model {
  static init(sequelize) {
    const columns = {
      channel_id: DataTypes.STRING,
      promo_id: DataTypes.INTEGER,
      title: DataTypes.STRING,
      target_type: DataTypes.STRING,
      target_selection: DataTypes.STRING,
      allocation_method:DataTypes.STRING,
      once_per_customer: DataTypes.BOOLEAN,
      customer_selection: DataTypes.STRING,
      entitled_product_ids: DataTypes.JSON,
      entitled_variant_ids: DataTypes.JSON,
      entitled_collection_ids: DataTypes.JSON,
      entitled_country_ids: DataTypes.JSON,
      prerequisite_saved_search_ids: DataTypes.JSON,
      prerequisite_subtotal_range: DataTypes.JSON,
      prerequisite_shipping_price_range: DataTypes.JSON
    }

    const options = {
      sequelize,
      underscored: true,
    }

    return super.init(columns, options)
  }

  static associate(models) {
    this.belongsTo(models.Promo);
  }
}

module.exports = ShopifyPriceRule;

连接

#!/usr/bin/env node
'use-strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');

function init(env, log) {
  const sequelize = new Sequelize({
    host: env.DB_HOST,
    username: env.DB_USER,
    password: env.DB_PASS,
    database: env.DB_SCHEMA,
    dialect: env.DB_DIALECT,
    logging: (msg) => log.debug({t: typeof msg }, msg),
    operatorsAliases: false,
  })

  const models =  Object.assign(
    {},
    ...fs.readdirSync(__dirname)
      .filter(file => ((file.indexOf('.') !== 0) && (file !== 'Index.js') && (file.slice(-3) === '.js')))
      .map(file => require(path.join(__dirname, file)) )
      .map(model => ({ [ model.name ]: model.init(sequelize) }))
  )

  Object.keys(models).forEach(model => ((typeof models[model].associate === 'function') && models[model].associate(models)) )

  return {
    models,
    Instance: sequelize,
    Class: Sequelize,
    Op: Sequelize.Op,
  }
}

module.exports = init