【发布时间】:2022-01-27 21:28:17
【问题描述】:
我正在使用sequelize: 6.9.0, sequelize-cli: ^6.3.0, express: 4.17.1, pg: 8.7.1
我在使用 sequelize findAndCountAll 时遇到问题,当我使用包含其他模型时,它会在我使用分页时返回相同的数据。
这是我的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
)
);
}
}
我的分页功能
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 };
假设我有 10 个数据 a,b,c,d,e,f,g,h,i,j
如果我看到第一页
http://localhost:3006/api/v1/house?size=5&page=1
它会返回 a,b,c,d,e(这是正确的)
如果我看到下一页
http://localhost:3006/api/v1/house?size=5&page=2
它会返回 e,d,c,b,a (只反向不显示 f,g,h,i,j)
如果我看到所有数据,它将返回正确的数据
http://localhost:3006/api/v1/house?size=10&page=1
它将返回 j,i,h,g,f,e,d,c,b,a
但如果我禁用了
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
使用分页时返回正确的数据。
House 的模型在这里
"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");
},
};
我也在其他表上使用相同的分页方法。但其他表工作正常,只有这张表搞砸了。
另一个名为Project函数的表在这里供参考
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
)
);
}
},
Project 模型
'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;
};
sequelize 为House page 1 生成 5 个数据的sql
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;
sequelize 为Project page 1 生成 5 个数据的sql
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";
有什么解决办法吗?非常感谢大家的帮助和关注!
【问题讨论】:
-
您是否尝试添加
order?如果您使用limit/offset,则应使用order以确保它限制了正确有序子集的记录。 -
哦,谢谢您提供的信息。我已经尝试过了,它可以工作。不知道为什么只有那个表不起作用,而其他具有相同配置的表工作正常。谢谢!
-
如果您与另一个表具有相同的配置,您可能希望该表也具有
order。如果没有order,您可能会得到意想不到的结果,即使它碰巧现在正在工作,也不能保证它会继续工作。
标签: sql node.js postgresql express sequelize.js