Skip to content

When using view.search() getting a undefined property error in QueryGenerator.js where() function #3

@jrcastillo

Description

@jrcastillo

Hi Guys, I'm using this package to make full text searches in my current system. I've followed the steps on how to implement the materialized views suggested on the documentation with no luck. I'm getting the following error

TypeError: Cannot read property 'field' of undefined
    at Object.keys.forEach.key (~/proj/node_modules/pg-search-sequelize/lib/queryGenerator.js:100:59)
    at Array.forEach (native)
    at QueryGenerator.where (~/proj//node_modules/pg-search-sequelize/lib/queryGenerator.js:97:29)
    at Function.search (~/proj/node_modules/pg-search-sequelize/lib/searchModel.js:82:8)

I've been trying to debug to see if I've implemented incorrectly but, it looks very alike to the example provided. I'll post the corresponding code below:

Express router

directorsRouter.get('/search',role_auth.isAdmin, (request, response) => {
  let query =  request.query ? request.query.q : 400;

  if(query === 400) {
    return response.json({
        status: query,
    })
  } else  {
    return models.DirectorMaterializedView.searchByText(query).catch(console.log);
  }
})

User.js (reference model)

'use strict';

let SearchModel = require("pg-search-sequelize");

module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('user', {
    name: {
      type: DataTypes.STRING
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false
    },
    role_id: {
      allowNull: false,
      type: DataTypes.INTEGER,
      references: {
        model: "role",
        key: "id"
      }
    },
    profile_pic: {
      type: DataTypes.STRING
    }
  });

  user.associate = (models) => {
    user.belongsTo(models.role, {
      foreignKey: 'role_id'
    })
    user.hasMany(models.director, {
      foreignKey: 'user_id',
      onDelete: 'CASCADE'
    })
    user.hasMany(models.teacher, {
      foreignKey: 'user_id',
      onDelete: 'CASCADE'
    })
    user.hasMany(models.student, {
      foreignKey: 'user_id',
      onDelete: 'CASCADE'
    })
  }

  user.hook("beforeCreate", "passwordHashing", (user, options) => {
    let hashedPassword = passwordHelper.hash(user.password)
    return user.password = hashedPassword
  })
  user.hook("afterCreate", "emailNotification", (user, options) => {
    // Asynchronous way to send an email without
    //   interrupting the flow of the system
    Mailer.sendPasswordWelcomeTemplate(user)
      .then(console.log)
      .catch(console.log)

    return user;
  })
  return user;
};

Materialized view implementation

'use strict';

const models = require("../models");

let SearchModel = require("pg-search-sequelize");

module.exports = (sequelize, DataTypes) => {
  let DirectorMaterializedView = sequelize.define('DirectorMaterializedView', {
      id: {type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true},
      name: DataTypes.STRING,
      email: DataTypes.TEXT,
      profile_pic: DataTypes.TEXT
  }, {
      tableName: 'director_materialized_view',
      timestamps: false,
      search: true,
      defaultScope: {
      attributes: {
        exclude: ['profile_pic', 'id']
        }
      },
      referenceModel: 'user' // The model for which we're defining the materialized view
  });

  return DirectorMaterializedView;
};

Index.js

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

Object.keys(models).forEach(key => {
  let model = models[key];
  if ('associate' in model) model.associate(models);

  if ('referenceModel' in model.options) model.referenceModel = models[model.options.referenceModel];

  if ('search' in model.options) new SearchModel(model);

  if ('customHooks' in model.options && 'afterSave' in model.options.customHooks) {
    let callback = () => model.options.customHooks.afterSave(models);
    model.afterCreate(callback);
    model.afterBulkCreate(callback);
    model.afterDestroy(callback);
    model.afterBulkDestroy(callback);
    model.afterUpdate(callback);
    model.afterBulkUpdate(callback);
  }
});

models.sequelize = sequelize;
models.Sequelize = Sequelize;

module.exports = models;

Sequelize migration

'use strict';

const QueryInterface = require("pg-search-sequelize").QueryInterface;
const models = require("../models");
const referenceModel = models.user;

const materializedViewName = "director_materialized_view";

const attributes = {
   name: "B",
   email: "A"
}

const options = {
    primaryKeyField: "id",
    include: [
        {
            model: models.director,
            foreignKey: "user_id",
            targetKey: "id",
            associationType: "hasOne", 
            attributes: { 
              phone: "D"
            }
        }
    ]
}

module.exports = {
  up: queryInterface => new QueryInterface(queryInterface).createMaterializedView(materializedViewName, referenceModel, attributes, options),

  down: queryInterface => new QueryInterface(queryInterface).dropMaterializedView(materializedViewName)
};

Any help with this will be greatly appreciated.

Extra information:

  • sequelize: 4.2.0
  • "pg-search-sequelize": "0.0.10"
  • node: 7.9.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions