AVOID DUPLICATES in sequelize query

Viewed 10290

i'm implementing a like system for a project. And I need some help with a query.

Basically i have 2 buttons (upvote and downvote) that call my function and give the id of a thread, the username voting, and the vote ( 1 or -1).

addPositiveorNegativeLikes = function(thread_id, username, vote) {

 sequelize.query('INSERT INTO Likes (thread_id, userId, vote, createdAt, updatedAt) 
 VALUES((?), (SELECT id FROM Users WHERE username=(?)), (?), (?), (?)) 
 ON DUPLICATE KEY UPDATE thread_id=(?), userId=(SELECT id FROM Users WHERE username=(?))',{

 replacements: [thread_id, username, vote, new Date(), new Date(), thread_id, username]
 }) 
}

But now in my Likes table althought thread_id and userId ara both primary keys, inserts multiple repeated "Likes".

How I can modify my query so it deletes an existing vote and replaces it for a new one??

Here is my Like model:

'use strict';
module.exports = (sequelize, DataTypes) => {
const Like = sequelize.define('Like', {
  id: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
  },
  userId: {
      allowNull: false,
      primaryKey: true,
      type: DataTypes.INTEGER
  },
  thread_id: {
      allowNull: false,
      primaryKey: true,
      type: DataTypes.INTEGER
  },
  createdAt: {
      allowNull: false,
      type: DataTypes.DATE
  },
  updatedAt: {
      allowNull: false,
      type: DataTypes.DATE
  },
  vote: {
      type: DataTypes.INTEGER
  }
}, {});
 Like.associate = function(models) {
 // associations can be defined here
 };
return Like;
};
1 Answers

Here , what you can do is , create a composite key , with this

userId: {
    allowNull: false,
    unique:"vote_user" // <------ HERE
    type: DataTypes.INTEGER
},
thread_id: {
    allowNull: false,
    unique:"vote_user" // <------ HERE
    type: DataTypes.INTEGER
},

NOTE :

 // Creating two objects with the same value will throw an error. The unique property can be either a
 // boolean, or a string. If you provide the same string for multiple columns, they will form a
 // composite unique key.
 uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex' },
 uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex' },

And then create it like :

Like.create({ userId : 1 , thread_id : 1 }).then(data => {
    // success
}).catch(err => {
    // error if same data exists
})
// <--- this will check that if there any entry with userId 1 and thread_id 1 , 
// if yes , then this will throw error
// if no then will create an entry for that

Note :

Never never run raw query , like you have did in your code sample , always use the model to perform CRUD , this way you can utilize all the features of sequelizejs

Related