I am using sequelize: 6.9.0, sequelize-cli: ^6.3.0, express: 4.17.1, pg: 8.7.1
i have a problem when using sequelize findAndCountAll, when i using include other models it will return same data when i'm using paging.
Here is my code for House Table
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo, project, isNew } =
req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = {};
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (project) {
filter.projectId = project;
}
if (isNew) {
filter.isNew = isNew;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.price = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.price = { [Op.gte]: firstPrice };
} else {
filter.price = { [Op.between]: [firstPrice, secondPrice] };
}
}
const HousesData = await Houses.findAndCountAll({
limit,
offset,
where: filter,
attributes: [
"id",
"name",
"description",
"location",
"price",
"tanah",
"bangunan",
"lantai",
"kamar_tidur",
"kamar_mandi",
"isNew",
],
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
});
if (HousesData) {
const response = getPagingData(HousesData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
}
my paging function
const getPagination = (page, size) => {
const newPage = page ? page - 1 : 0;
const limit = size ? +size : 10;
const offset = newPage != 0 ? newPage * limit : 0;
return { limit, offset };
};
const getPagingData = (data, page, limit) => {
const { count: totalItems, rows: dataRows } = data;
const currentPage = page ? +page : 1;
const totalPages = Math.ceil(totalItems / limit);
return { totalItems, totalPages, currentPage, dataRows };
};
module.exports = { getPagination, getPagingData };
Let's say i have 10 data
a,b,c,d,e,f,g,h,i,j
if i see first page
http://localhost:3006/api/v1/house?size=5&page=1
it will return a,b,c,d,e (this is right)
and if i see next page
http://localhost:3006/api/v1/house?size=5&page=2
it will return e,d,c,b,a (only reverse not showing f,g,h,i,j)
and if i see all the data it will return correct data
http://localhost:3006/api/v1/house?size=10&page=1
it will return j,i,h,g,f,e,d,c,b,a
but if i disabled
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
it return the right data when use paging.
my model for House is here
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Houses", {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.STRING(22),
},
name: {
type: Sequelize.STRING,
},
projectId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Projects",
key: "id",
},
},
cityId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Cities",
key: "id",
},
},
developerId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Developers",
key: "id",
},
},
description: {
type: Sequelize.TEXT,
},
location: {
type: Sequelize.STRING,
},
price: {
type: Sequelize.BIGINT,
},
tanah: {
type: Sequelize.INTEGER,
},
bangunan: {
type: Sequelize.INTEGER,
},
lantai: {
type: Sequelize.INTEGER,
},
kamar_tidur: {
type: Sequelize.INTEGER,
},
kamar_mandi: {
type: Sequelize.INTEGER,
},
house_thumbnail: {
type: Sequelize.STRING,
},
isNew: {
type: Sequelize.BOOLEAN,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Houses");
},
};
i also use same paging method on other table. but other table works fine, only this table that got messed up.
the other table named Project function is here for reference
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo } = req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = { haveDeveloper: true };
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.minPrice = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.minPrice = { [Op.gte]: firstPrice };
} else {
filter.minPrice = { [Op.between]: [firstPrice, secondPrice] };
}
}
const projectsData = await Projects.findAndCountAll({
limit,
offset,
where: filter,
attributes: ["id", "name", "image", "location",'minPrice'],
include: [
{ model: Cities, attributes: ["id", "name"] },
{ model: Developers, attributes: ["id", "name"] },
{ model: ProjectFacilities, attributes: ["facility"] },
],
});
if (projectsData) {
const response = getPagingData(projectsData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
},
the Project model
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Projects extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Projects.belongsTo(models.Developers, { foreignKey: 'developerId' })
Projects.belongsTo(models.Cities, { foreignKey: 'cityId' })
Projects.hasMany(models.ProjectFacilities, { foreignKey: 'projectId' })
Projects.hasMany(models.Houses, { foreignKey: 'projectId' })
}
};
Projects.init({
name: DataTypes.STRING,
image: DataTypes.STRING,
description: DataTypes.TEXT,
location: DataTypes.STRING,
minPrice:DataTypes.BIGINT,
haveDeveloper: DataTypes.BOOLEAN,
cityId: DataTypes.STRING,
developerId: DataTypes.INTEGER
}, {
sequelize,
modelName: 'Projects',
});
return Projects;
};
sql generated by sequelize for House page 1 with 5 data
SELECT "Houses"."id", "Houses"."name", "Houses"."description", "Houses"."location", "Houses"."price", "Houses"."tanah", "Houses"."bangunan", "Houses"."lantai", "Houses"."kamar_tidur", "Houses"."kamar_mandi", "Houses"."isNew", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "City"."id" AS "City.id", "City"."name" AS "City.name", "Project"."id" AS "Project.id", "Project"."name" AS "Project.name" FROM "Houses" AS "Houses" LEFT OUTER JOIN "Developers" AS "Developer" ON "Houses"."developerId" = "Developer"."id" LEFT OUTER JOIN "Cities" AS "City" ON "Houses"."cityId" = "City"."id" LEFT OUTER JOIN "Projects" AS "Project" ON "Houses"."projectId" = "Project"."id" LIMIT 5 OFFSET 0;
sql generated by sequelize for Project page 1 with 5 data
SELECT "Projects".*, "City"."id" AS "City.id", "City"."name" AS "City.name", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "ProjectFacilities"."id" AS "ProjectFacilities.id", "ProjectFacilities"."facility" AS "ProjectFacilities.facility" FROM (SELECT "Projects"."id", "Projects"."name", "Projects"."image", "Projects"."location", "Projects"."minPrice", "Projects"."cityId", "Projects"."developerId" FROM "Projects" AS "Projects" WHERE "Projects"."haveDeveloper" = true LIMIT 5 OFFSET 0) AS "Projects" LEFT OUTER JOIN "Cities" AS "City" ON "Projects"."cityId" = "City"."id" LEFT OUTER JOIN "Developers" AS "Developer" ON "Projects"."developerId" = "Developer"."id" LEFT OUTER JOIN "ProjectFacilities" AS "ProjectFacilities" ON "Projects"."id" = "ProjectFacilities"."projectId";
is there any solution for this? thank you very much for your all help and attention!
Please try thi
const getPagination = (page = 1, size = 10) => {
const offset = (page - 1) * size ;
const limit = size ;
return { limit, offset };
};
I'm trying to use the Jodit editor and wish to use the image uploading capabilities to specify a folder and path of where to upload it to using a PHP script.
I'm trying to put in some console.log statements to check my values, but when I select an image, I receive this error in the console which I don't know how to fix.
The code I've used in the page is:
<script>
var editor = new Jodit('#editor_Jodit',{
enableDragAndDropFileToEditor: true,
uploader: {
url: 'connector/upload.php',
format: 'json',
pathVariableName: 'path',
filesVariableName: 'images',
prepareData: function (data) {
return data;
},
isSuccess: function (resp) {
return !resp.error;
},
getMsg: function (resp) {
return resp.msg.join !== undefined ? resp.msg.join(' ') : resp.msg;
},
process: function (resp) {
return {
files: resp[this.options.uploader.filesVariableName] || [],
path: resp.path,
baseurl: resp.baseurl,
error: resp.error,
msg: resp.msg
};
},
error: function (e) {
this.events.fire('errorPopap', [e.getMessage(), 'error', 4000]);
},
defaultHandlerSuccess: function (data, resp) {
var i, field = this.options.uploader.filesVariableName;
if (data[field] && data[field].length) {
for (i = 0; i < data[field].length; i += 1) {
this.selection.insertImage(data.baseurl + data[field][i]);
}
}
},
defaultHandlerError: function (resp) {
this.events.fire('errorPopap', [this.options.uploader.getMsg(resp)]);
}
}
});
editor.value = '<p>start</p>';
</script>
Try to remove the following line:
filesVariableName: 'images'
Replace with a function
filesVariableName: function (r) {
return 'images'
},
A little background
Well, I was trying to use upsert command, however I keep getting errors, and I had no idea what went wrong, I already input the object that I want upsert (that is NewIssue) which is a value based on other call.
What it does
Error :(
{
"name": "SequelizeDatabaseError",
"parent": {
"fatal": false,
"errno": 1064,
"sqlState": "42000",
"code": "ER_PARSE_ERROR",
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
},
"original": {
"fatal": false,
"errno": 1064,
"sqlState": "42000",
"code": "ER_PARSE_ERROR",
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
},
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
}
My code
Data Schema:
const Issue = sequelize.define('ms_issue', {
id_Issue: {
type: Sequelize.NUMBER,
primaryKey: true
},
id_IssueTag: {
type: Sequelize.NUMBER,
},
datetime_Issued: {
type: Sequelize.NOW
},
subject_Issue: {
type: Sequelize.STRING
},
desc_Issue: {
type: Sequelize.STRING
},
status_Issue: {
type: Sequelize.STRING
}
}, { timestamps: false, freezeTableName: true });
app.put('/issues/:id', (req, res) => {
const id_Staff = req.body.id_Staff
if (typeof id_Staff !== 'undefined' && typeof id_Staff === 'number') {
const id_Issue = parseInt(req.params.id)
if (typeof id_Issue !== 'undefined' && typeof id_Issue === 'number') {
Issue.findByPk(id_Issue)
.then(issue => {
if (issue) {
const newIssue = {
subject_Issue: req.body.subject || undefined,
desc_Issue: req.body.description || undefined,
id_IssueTag: req.body.tag || undefined
}
for (const obj in newIssue) {
if (typeof newIssue[obj] !== 'undefined') {
issue[obj] = newIssue[obj]
}
}
const NewIssue = issue
return NewIssue
} else res.status(404).send("Issue not found")
})
.then(NewIssue => {
return Issue.upsert(NewIssue)
.then(bool => {
if (bool === true) {
res.status(200).send("Issue has been updated")
res.status(200).send(NewIssue)
}
})
.catch(err => {
res.status(500).send(err)
})
})
.catch(err => {
console.log(err)
res.status(500).send("Cannot connect to database")
})
} else {
res.status(400).send("Invalid parameters: require 'id_Issue'")
}
} else {
res.status(401).send("Unauthorized access")
}
})
What I wanted
Able to insert/update on request in MariaDB. And explanation :)
The generated SQL is invalid - there are no values:
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
The SQL should be valid if you specify, roughly as below:
...
Issue.upsert({
id_Issue: id_Issue,
subject_Issue: NewIssue.subject_Issue,
id_IssueTag : NewIssue.id_IssueTag,
...
I am using vue2-dropzone library and my complaint is the ref value of a dropzone component doesn't contain the file user droped.
After user adds the second file the ref of dropzone contains only previous one.
But it works correctly when user select on file dialog.
<vue-dropzone ref="docfile" id="dropzone" :options="dzOptions"></vue-dropzone>
dzOptions: {
url: self.$apiUrl + "client/documents/",
autoProcessQueue: false,
acceptedFiles: "application/pdf",
uploadMultiple: false,
maxNumberOfFiles: 1,
maxFilesize: 30,
addRemoveLinks: true,
dictDefaultMessage: "Select File",
init: function() {
this.on("addedfiles", function(files) {
if (files.length > 1) {
self.$toaster.error("You can upload only one.");
this.removeAllFiles();
return;
}
if (files[0].type != "application/pdf") {
self.$toaster.error("You can upload only pdf file.");
this.removeAllFiles();
return;
}
self.upload();
});
}
}
upload() {
var self = this;
if (self.$refs.docfile.dropzone.files.length == 0) {
self.$toaster.error("No document to upload.");
return;
}
var filePath = self.$refs.docfile.dropzone.files[0];
...
}
You are accessing your references like this:
self.$refs.docfile.dropzone
Try like this:
self.$refs.docfile
As per the files, you could get them with the: getAcceptedFiles(), getRejectedFiles(), getQueuedFiles() methods.
Some example on how to use vue-uploads events:
data: () => ({
dropzoneOptions: {
...
},
myFiles: []
}),
<vue-dropzone ref="myVueDropzone" id="dropzone"
:options="dropzoneOptions"
#vdropzone-success="filesUploaded">
</vue-dropzone>
filesUploaded(event){
this.myFiles.push(JSON.parse(event.xhr.response));
},
I found that there is a delay when user drag a file.
So I have fixed this issue using timeout in dropzone option like following.
dzOptions: {
url: self.$apiUrl + "client/documents/",
autoProcessQueue: false,
acceptedFiles: "application/pdf",
uploadMultiple: false,
maxNumberOfFiles: 1,
maxFilesize: 30,
addRemoveLinks: true,
dictDefaultMessage:
"Select File",
init: function() {
this.on("addedfiles", function(files) {
var dz = this;
setTimeout(function() {
self.upload();
}, 500);
});
}
}