在Node API混乱中使用knex.js编写插入语句

时间:2015-05-19 17:15:10

标签: javascript node.js postgresql knex.js

我有一个问题,我似乎无法真正包围我的脑袋。它非常特定于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个“项目”的块。我已经在项目中发布了一个问题(https://github.com/tgriesser/knex/issues/826),但我希望Knex.JS社区的一些人在SO上更活跃。

2 个答案:

答案 0 :(得分:3)

你的解决方案是正确的(承诺链接),但是既然你正在使用Knex,那么Bluebird附带了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);
  });
});

答案 1 :(得分:0)

我找到了解决方案。我并不完全相信这个问题是Knex.js的错,或者它是否是我自己缺乏Promise的经验。

我在Tim Griesser所做的工作中找到了灵感:See More

基本上他所做的就是将一块块添加到一个承诺链中。也许这可以直接在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));