有熟练sequelizejs的吗 Nodejs
有熟练sequelizejs的吗 Nodejs
现在项目中再用,数据库是MySQL,现在的实现方式把自己绕进死胡同了
逻辑上是以 customers
表的 id
为主键,在 shops
表和 devices
表中的 customer_id
为外键,进行增减查删,返还给前端:[{id: #, shop: #, device: #}, {id: #, shop: #, device: #}]
格式的数据
之前写的代码如下:
Customers
// 声明一个全局变量保存数据
var CUSTOMER_DATA = []
var Customers = db.define(‘customers’, {
id: Sequelize.INTEGER
})
Shops
var Shops = db.define('shops', {}, {
classMethods: {
// 根据customer_id和参数id匹配,计算Shops中匹配的总数
countShop: function (id, callback) {
Shops
.count({
where: {
company_id: id
}
})
.complete(function (num) {
callback(num)
})
}
}
})
//(Devices代码同Shops大同小异)
最终计算代码
Customers
.findAll()
.complete(function (error, customers) {
customers.each(function (customer) {
var data = {}
data.id = customer.dataValues.id
// 根据data.id,计算shops数量
Shops.countShop(data.id, function (num) {
data.shop = num
// 把格式正确的数据放到全局变量中,这里卡住了,异步的话怎么确定each执行完了然后暴露出来
CUSTOMER_DATA.push(data)
})
})
})
感谢任何有帮助的回答!
当然可以。根据你的描述,你当前的实现方式使用了全局变量来存储结果,这不仅不利于代码的可维护性,还可能引入并发问题。我们可以使用 Sequelize 的关联功能来简化查询,并且通过 Promise 来处理异步操作。
首先,我们需要定义模型之间的关系。假设 customers
、shops
和 devices
之间存在一对多的关系,我们可以这样定义模型:
const db = require('./db'); // 引入 Sequelize 实例
const Customer = db.define('customers', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: Sequelize.STRING // 假设有一个名称字段
});
const Shop = db.define('shops', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
customerId: {
type: Sequelize.INTEGER,
allowNull: false
}
});
const Device = db.define('devices', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
customerId: {
type: Sequelize.INTEGER,
allowNull: false
}
});
// 定义关联
Customer.hasMany(Shop, { foreignKey: 'customerId' });
Customer.hasMany(Device, { foreignKey: 'customerId' });
module.exports = {
Customer,
Shop,
Device
};
接下来,我们可以通过 Sequelize 的关联方法来获取所需的数据。这里是一个示例代码,展示了如何获取每个客户的店铺和设备数量:
const { Customer, Shop, Device } = require('./models');
async function getCustomerData() {
const customers = await Customer.findAll({
include: [
{
model: Shop,
attributes: []
},
{
model: Device,
attributes: []
}
],
attributes: ['id', [db.literal('(SELECT COUNT(*) FROM shops WHERE shops.customerId = customers.id)'), 'shopCount'], [db.literal('(SELECT COUNT(*) FROM devices WHERE devices.customerId = customers.id)'), 'deviceCount']]
});
return customers.map(customer => ({
id: customer.id,
shop: customer.shopCount,
device: customer.deviceCount
}));
}
getCustomerData().then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
在这个示例中,我们使用了 Sequelize 的 findAll
方法,并通过 include
选项将 Shop
和 Device
模型包含进来。为了计算每个客户的店铺和设备数量,我们使用了 db.literal
来执行子查询。最后,我们将结果映射成所需的格式。
这种方法避免了使用全局变量,并且通过 Promise 处理异步操作,使得代码更加清晰和易于维护。希望这对你有所帮助!
不明觉历
用Q
数组循环处理建议使用forEach
从你的描述来看,你希望通过 sequelizejs
实现对 customers
、shops
和 devices
表的查询,并返回特定格式的数据。目前的实现方式遇到了异步问题,导致无法正确地收集所有结果。
下面是改进后的代码示例,使用 Promise.all
来处理异步操作:
改进后的代码
定义模型
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('mysql://username:password@localhost:3306/database');
const Customers = sequelize.define('customers', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
}
});
const Shops = sequelize.define('shops', {
customerId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Customers,
key: 'id'
}
}
});
const Devices = sequelize.define('devices', {
customerId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Customers,
key: 'id'
}
}
});
查询并返回数据
async function getCustomerData() {
const customers = await Customers.findAll();
const customerPromises = customers.map(async (customer) => {
const shopCount = await Shops.count({ where: { customerId: customer.id } });
const deviceCount = await Devices.count({ where: { customerId: customer.id } });
return {
id: customer.id,
shop: shopCount,
device: deviceCount
};
});
const customerData = await Promise.all(customerPromises);
return customerData;
}
getCustomerData().then(data => {
console.log(data); // [{id: #, shop: #, device: #}, {id: #, shop: #, device: #}]
}).catch(error => {
console.error(error);
});
解释
- 定义模型:使用
Sequelize
定义Customers
、Shops
和Devices
模型,并设置外键关联。 - 查询函数:定义一个异步函数
getCustomerData
,该函数首先获取所有的Customers
,然后对每个客户执行异步查询以统计其Shops
和Devices
的数量。 - 使用
Promise.all
:将所有异步查询封装在一个数组中,并使用Promise.all
等待所有查询完成。这样可以确保所有查询完成后才返回结果。 - 返回结果:最后返回格式化的数据。
这种方法避免了使用全局变量和回调地狱,使代码更加清晰和易于维护。