在节点 API 上使用 knex.js 编写插入语句混淆
Writing insert statements with knex.js on Node API confusion
我有一个问题,我似乎无法真正解决。它非常特定于 Knex.JS 实现,我确定与 PostgreSQL 无关。
以下实现有效。插入适量时(~500 条语句)。由于其他原因,在较大的数量上失败。无论如何,以下内容不适用于我的用例,我需要类似于下一节的内容。
import knex = require("knex");
(function (items) {
let db = knex.table("items");
db.truncate();
let foo = [];
items.forEach(function(item) {
foo.push({
id : item.id,
item_data : JSON.stringify(item)
});
});
db.insert(foo).then(function () { /*..*/ });
}(items))
但以下不是:
import knex = require("knex");
(function (items) {
let db = knex.table("items");
db.truncate();
let foo = [];
items.forEach(function(item) {
db.then(function() {
return db.insert(foo).into("items");
});
});
db.then(function () { console.log("Done"); });
}(items))
这是行不通的:
- 插入的行数不一致。在某些实现中,它比我拥有的物品多得多 (?!)
- 我在这个实现中遇到了很多重复的键错误,因为我有一个唯一的约束
附加信息:
- 该集合不包含重复键
- 我正在使用 PostgreSQL 作为后端
问题主要是如何实现所需的行为。理想的情况是处理 500 "items" 块。我已经针对该项目 (https://github.com/tgriesser/knex/issues/826) 发布了一个问题,但我希望 Knex.JS 社区的某些人在 SO 上更加活跃。
我找到了解决方案。我不完全相信这个问题是 Knex.js 的错,或者是我自己缺乏一般的 Promises 经验。
我在 Tim Griesser 所做的工作中找到了灵感:https://github.com/tgriesser/knex/blob/batch-insert/lib/util/batch-insert.js
基本上他所做的就是将块添加到承诺链中。也许这可以直接在 Knex 库上完成,但为了便于阅读,我将其分开。
import knex = require("knex");
(function (items) {
let db = knex.table("items");
// This is the basic operation to add a promise to the chain.
chain = chain.then(function() { return db.truncate(); });
let foo = [];
items.forEach(function(item) {
// Add db.insert() promises to our promise chain
// This can easily be changed to include chunks and/or streams
chain = chain.then(function () {
return db.insert(item);
});
});
// Start resolving the promises once our db.then() is invoked.
return db.then(function(){
return chain.then();
});
}(items));
您的解决方案是正确的(承诺链接),但是由于您使用的是 Knex,它随 Bluebird 一起提供,它已经为此提供了一个实用方法:
var Promise = require("bluebird"); // also used internally by Knex so free to require
Promise.each(items, db.insert.bind(db));
会做同样的事情:
items.forEach(function(item) {
chain = chain.then(function () {
return db.insert(item);
});
});
我有一个问题,我似乎无法真正解决。它非常特定于 Knex.JS 实现,我确定与 PostgreSQL 无关。
以下实现有效。插入适量时(~500 条语句)。由于其他原因,在较大的数量上失败。无论如何,以下内容不适用于我的用例,我需要类似于下一节的内容。
import knex = require("knex");
(function (items) {
let db = knex.table("items");
db.truncate();
let foo = [];
items.forEach(function(item) {
foo.push({
id : item.id,
item_data : JSON.stringify(item)
});
});
db.insert(foo).then(function () { /*..*/ });
}(items))
但以下不是:
import knex = require("knex");
(function (items) {
let db = knex.table("items");
db.truncate();
let foo = [];
items.forEach(function(item) {
db.then(function() {
return db.insert(foo).into("items");
});
});
db.then(function () { console.log("Done"); });
}(items))
这是行不通的:
- 插入的行数不一致。在某些实现中,它比我拥有的物品多得多 (?!)
- 我在这个实现中遇到了很多重复的键错误,因为我有一个唯一的约束
附加信息:
- 该集合不包含重复键
- 我正在使用 PostgreSQL 作为后端
问题主要是如何实现所需的行为。理想的情况是处理 500 "items" 块。我已经针对该项目 (https://github.com/tgriesser/knex/issues/826) 发布了一个问题,但我希望 Knex.JS 社区的某些人在 SO 上更加活跃。
我找到了解决方案。我不完全相信这个问题是 Knex.js 的错,或者是我自己缺乏一般的 Promises 经验。
我在 Tim Griesser 所做的工作中找到了灵感:https://github.com/tgriesser/knex/blob/batch-insert/lib/util/batch-insert.js
基本上他所做的就是将块添加到承诺链中。也许这可以直接在 Knex 库上完成,但为了便于阅读,我将其分开。
import knex = require("knex");
(function (items) {
let db = knex.table("items");
// This is the basic operation to add a promise to the chain.
chain = chain.then(function() { return db.truncate(); });
let foo = [];
items.forEach(function(item) {
// Add db.insert() promises to our promise chain
// This can easily be changed to include chunks and/or streams
chain = chain.then(function () {
return db.insert(item);
});
});
// Start resolving the promises once our db.then() is invoked.
return db.then(function(){
return chain.then();
});
}(items));
您的解决方案是正确的(承诺链接),但是由于您使用的是 Knex,它随 Bluebird 一起提供,它已经为此提供了一个实用方法:
var Promise = require("bluebird"); // also used internally by Knex so free to require
Promise.each(items, db.insert.bind(db));
会做同样的事情:
items.forEach(function(item) {
chain = chain.then(function () {
return db.insert(item);
});
});