Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize: multiple belongsTo and hasMany issue

My schema consists of users and reviews. Basically, each user can leave a review on another user. Since I need to get all reviews from a user that was reviewed only, I wrote the following associations:

User.hasMany(Review, { as: 'reviews', foreignKey: { name: 'reviewee', allowNull: false } });
Review.belongsTo(User, { as: 'user', foreignKey: { name: 'reviewee', allowNull: false } });
Review.belongsTo(User, { as: 'author', foreignKey: { name: 'reviewer', allowNull: false } });

When I try to get user reviews

User.findById(1, {
  include: [{
    model: Review,
    as: 'reviews'
  }]
}).then((user) => {
  console.log(user.reviews);
});

it gives this error

SequelizeDatabaseError: SQLITE_ERROR: no such column: reviews.reviewee

EDIT: Here are the models

const User = sequelize.define('User', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: Sequelize.STRING, allowNull: false, unique: true },
  email: { type: Sequelize.STRING, allowNull: false, unique: true },
  phone_number: { type: Sequelize.STRING, allowNull: false, unique: true },
  last_login: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.NOW },
  password: { type: Sequelize.STRING, allowNull: false },
  verified_email: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false },
  verified_phone: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false },
  verified_id: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false },
  password_change_date: { type: Sequelize.DATE, allowNull: false, defaultValue: Sequelize.NOW },
  role: { type: Sequelize.ENUM('admin', 'user'), allowNull: false, defaultValue: 'user' }
});

const Review = sequelize.define('Review', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
  text: { type: Sequelize.STRING, allowNull: false },
});
like image 865
Kudayar Pirimbaev Avatar asked May 18 '18 07:05

Kudayar Pirimbaev


People also ask

How do you use belongsTo in Sequelize?

You can make the Task model belongs to the User model by calling the belongsTo() method from the Task model like this: Task. belongsTo(User); The belongsTo() method above will associate the Task model with the User model, adding the UserId attribute to the Task model as the foreign key constraint.


1 Answers

This does the trick. I just rely on the default implementation of belongsTo.

const Sequelize = require('sequelize');
const sequelize = new Sequelize('user', 'pwd', 'localhost', {
    dialect: 'sqlite',
    operatorsAliases: false,
    pool: {
        max: 5,
        min: 0,
        acquire: 30000,
        idle: 10000
    },
    storage: 'users-review.sqlite'
});

const User = sequelize.define('user', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    name: {
        type: Sequelize.STRING,
        allowNull: false,
        unique: true
    },
    password: {
        type: Sequelize.STRING,
        allowNull: false
    }
});

const Review = sequelize.define('review', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    text: {
        type: Sequelize.TEXT,
        allowNull: false
    }
});

User.hasMany(Review, {
    foreignKey: 'revieweeId',
    allowNull: false
});

Review.belongsTo(User, {
    as: 'reviewer'
});

Review.belongsTo(User, {
    as: 'reviewee'
});

sequelize.sync({
    force: true
}).then(() =>
    // create some users
    User.bulkCreate([
        { name: 'user1', password: 'pwd1' },
        { name: 'user2', password: 'pwd2' }
    ])
    .then(() => {
        return User.findAll();
    })
    // and set the associations
    .then(users => {
        let [ user1, user2 ] = users;
        return Review.create({
            text: 'about user2'
        })
        .then(review => {
            return review.setReviewer(user1).then(review => {
                return review.setReviewee(user2).then(review => {
                    return user1.addReview(review).then(() => {
                        return review;
                    });
                })
            })
        })
    })
    .then(review => {
        review.getReviewer().then(u => console.log(
            'reviewer', u.toJSON()));
        review.getReviewee().then(u => console.log(
            'reviewee', u.toJSON()));
    })
    .then(() => {
        return User.findById(1, {
            include: [ Review ]
        });
    })
    .then(user => {
        console.log('user', user.toJSON());
        user.getReviews().then(reviews =>
            reviews.forEach(r =>
                console.log("review", r.toJSON())));
    }));
like image 177
chriopp Avatar answered Oct 04 '22 23:10

chriopp