仅当唯一时使用 knex 插入
Insert only if unique using knex
我正在编写一个 Node.js 脚本,它接受一组对象,这些对象代表记录不同测量值的不同设备。我想使用 Knex.js 在 PSQL 数据库中存储有关设备的信息,但只想存储来自表示 new/unique 设备的对象的设备信息。只要同一设备出现在不同的 POST 请求中,插入前 device_id 的验证似乎就可以工作。但是当相同的设备出现时
在同一个 POST 请求中,似乎程序的异步性质导致验证在插入完成之前发生。
我尝试让脚本调用两个单独的异步等待函数(一个用于验证,另一个用于实际插入)但不确定这是否是最简单的方法,或者我是否做对了,因为它无论如何都失败了.
app.post('/testsite', (req, res) => {
const data = (req.body.measurements);
for (let i = 0; i < data.length; i++) {
database.select("device_id").from("device_info").where("device_id", data[i].device_id)
.then(MatchList => {
console.log(MatchList);
if (MatchList.length === 0) {
return database('device_info')
.returning('device_id')
.insert({
device_id: data[i].device_id,
device_name: data[i].device_name,
site_id: data[i].site_id,
site_name: data[i].site_name
})
.then((newdevice) => {
console.log('inserted device id', newdevice);
});
}
return;
});
}
});
我希望它在验证失败时不会插入,但似乎验证永远不会失败,即使它应该失败,我得到这个错误:
Unhandled rejection error: duplicate key value violates unique constraint "device_info_pkey"
我不确定这个问题是由于 knex 的异步性质造成的,还是其他原因造成的。但是,我 re-wrote 你的代码使用 async/await 语法以使其更具可读性。自从我添加 .first()
后,我还只是检查设备是否返回为 null 而不是数组。你能检查一下当你调用这个函数时 device
是否得到控制台记录吗?
app.post('/testsite', async (req, res) => {
const data = (req.body.measurements);
for (let i = 0; i < data.length; i++) {
const device = await database
.select('*')
.from('device_info')
.where('device_id', data[i].device_id)
.first();
console.log(device);
if (device) {
const newDevice = await database
.from('device_info')
.insert({
device_id: data[i].device_id,
device_name: data[i].device_name,
site_id: data[i].site_id,
site_name: data[i].site_name
})
.returning('*');
return newDevice;
} else {
return device;
}
}
});
我终于解决了这个问题。本质上,仅在搜索和插入时使用 async await 是不够的,因为 for 循环仍会移动到下一个元素。为了解决这个问题,我让 POST 请求调用了一个异步函数。
app.post('/testsite', (req,res) =>
{ const data = (req.body.measurements);
postfxn(data); } )
此函数等待 for 循环的每次迭代。
async function postfxn(data){
for(let i =0; i<data.length; i++){
await insertdevice(data[i]); }
}
插入设备功能然后使用异步等待来搜索设备,如果它不在数据库中,则按照 technogeek1996 的回答所建议的那样插入。
希望这对遇到类似问题的其他人有所帮助
我正在编写一个 Node.js 脚本,它接受一组对象,这些对象代表记录不同测量值的不同设备。我想使用 Knex.js 在 PSQL 数据库中存储有关设备的信息,但只想存储来自表示 new/unique 设备的对象的设备信息。只要同一设备出现在不同的 POST 请求中,插入前 device_id 的验证似乎就可以工作。但是当相同的设备出现时 在同一个 POST 请求中,似乎程序的异步性质导致验证在插入完成之前发生。
我尝试让脚本调用两个单独的异步等待函数(一个用于验证,另一个用于实际插入)但不确定这是否是最简单的方法,或者我是否做对了,因为它无论如何都失败了.
app.post('/testsite', (req, res) => {
const data = (req.body.measurements);
for (let i = 0; i < data.length; i++) {
database.select("device_id").from("device_info").where("device_id", data[i].device_id)
.then(MatchList => {
console.log(MatchList);
if (MatchList.length === 0) {
return database('device_info')
.returning('device_id')
.insert({
device_id: data[i].device_id,
device_name: data[i].device_name,
site_id: data[i].site_id,
site_name: data[i].site_name
})
.then((newdevice) => {
console.log('inserted device id', newdevice);
});
}
return;
});
}
});
我希望它在验证失败时不会插入,但似乎验证永远不会失败,即使它应该失败,我得到这个错误:
Unhandled rejection error: duplicate key value violates unique constraint "device_info_pkey"
我不确定这个问题是由于 knex 的异步性质造成的,还是其他原因造成的。但是,我 re-wrote 你的代码使用 async/await 语法以使其更具可读性。自从我添加 .first()
后,我还只是检查设备是否返回为 null 而不是数组。你能检查一下当你调用这个函数时 device
是否得到控制台记录吗?
app.post('/testsite', async (req, res) => {
const data = (req.body.measurements);
for (let i = 0; i < data.length; i++) {
const device = await database
.select('*')
.from('device_info')
.where('device_id', data[i].device_id)
.first();
console.log(device);
if (device) {
const newDevice = await database
.from('device_info')
.insert({
device_id: data[i].device_id,
device_name: data[i].device_name,
site_id: data[i].site_id,
site_name: data[i].site_name
})
.returning('*');
return newDevice;
} else {
return device;
}
}
});
我终于解决了这个问题。本质上,仅在搜索和插入时使用 async await 是不够的,因为 for 循环仍会移动到下一个元素。为了解决这个问题,我让 POST 请求调用了一个异步函数。
app.post('/testsite', (req,res) =>
{ const data = (req.body.measurements);
postfxn(data); } )
此函数等待 for 循环的每次迭代。
async function postfxn(data){
for(let i =0; i<data.length; i++){
await insertdevice(data[i]); }
}
插入设备功能然后使用异步等待来搜索设备,如果它不在数据库中,则按照 technogeek1996 的回答所建议的那样插入。
希望这对遇到类似问题的其他人有所帮助