插入后 Knex 解析空集

Posted

技术标签:

【中文标题】插入后 Knex 解析空集【英文标题】:Knex resolving empty set after insert 【发布时间】:2017-01-15 10:24:58 【问题描述】:

我正在尝试使用 Postgresql 和 Knex 在 Node 中设置一个基本的数据库连接,但我无法让看似简单的插入工作。我将大部分代码基于 Knex github repo 中的示例代码。

问题似乎是我的第一个插入(我在其中添加管理员用户)正在解析一组空行(不太确定,因为文档不包含任何关于行或行集的信息)找到)。

这是我的代码:

const knex = require("knex")(
  client: "postgres",
  connection: 
    host     : "127.0.0.1",
    user     : "postgres",
    password : "my password goes here",
    database : "issue-tracker",
    charset  : "utf8"
  
);

knex.schema
  .dropTableIfExists("tickets")
  .dropTableIfExists("users")
  .createTable("users", createUserTable)
  .createTable("tickets", createTicketTable)
  .then(() => addTestData())
  .then(() => console.log("Done"))
  .catch((e) => console.log(e));

function createUserTable(table) 
  table.increments("id");
  table.string("username").index().unique();
  table.string("password");
  table.timestamps();


function createTicketTable(table) 
  table.increments("id");
  table.timestamps();
  table.integer("creator_id").unsigned().references("users.id");
  table.string("text");


function addTestData() 
  return Promise.resolve()
    .then(() =>
      knex.insert(username: "admin", password: "password")
      .into("users")
    )
    .then((rows) =>
      // rows is empty?
      knex.insert(creator_id: rows[0], text: "this is a test")
      .into("tickets")
    )
    .then(() =>
      knex("users").join("tickets", "users.id", "tickets.creator_id")
      .select("users.id as creator_id", "users.username as creator_name", "tickets.text as text")
    )
    .then(console.log.bind(console));

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

Promise 处理程序必须返回一些东西。它就像一条流水线一样工作——每个工作站都必须将其工作成果放回生产线上。

knex 中的插入操作不会返回行,除非您明确告诉它们返回。 Knex 对此有 .returning() (docs)。 链中的最后一个处理程序 (console.log.bind(console)) 不返回任何内容,因此链的最终结果是未定义的。 您不需要以Promise.resolve() 启动承诺链。您可以使用任何返回承诺的函数来启动它 - 在这里直接使用 knex() 是明智的。

所以,稍微重新安排一下,我们最终得到了这个:

function addTestData() 
    return knex("users")
        .returning("user_id")
        .insert(username: "admin", password: "password")
        .then((rows) => 
            return knex("tickets")
                .returning("ticket_id")
                .insert(creator_id: rows[0], text: "this is a test");
        )
        .then((rows) => 
            return knex("users")
                .join("tickets", "users.id", "tickets.creator_id")
                .select("users.id as creator_id", "users.username as creator_name", "tickets.text as text");
        )
        .then((rows) => 
            console.log.bind(console);
            return rows;
        );

这等同于这个,return 是隐含的,因此不太明显:

function addTestData() 
    return knex("users")
        .returning("user_id")
        .insert(username: "admin", password: "password")
        .then((rows) => knex("tickets")
            .returning("ticket_id")
            .insert(creator_id: rows[0], text: "this is a test");
        )
        .then((rows) => knex("users")
            .join("tickets", "users.id", "tickets.creator_id")
            .select("users.id as creator_id", "users.username as creator_name", "tickets.text as text");
        )
        .then((rows) => 
            console.log.bind(console);
            return rows;
        );

【讨论】:

这不是问题。我不想解决任何价值。我只是想插入一个用户,解析它的 id,然后插入一张票(它的 creator_id 设置为插入的用户的 id)。 addTestData 无法解决任何我关心的问题。问题是rows在第一次插入后为空。 啊。 Insert 语句通常不返回任何行。有关获取插入值的方法,请参阅github.com/tgriesser/knex/issues/732。 谢谢!问题是我没有使用returning 方法。它现在工作。如果您想修改答案,我会接受。 我一回家就编辑它。我没有准备好在手机上做这件事的痛苦。 :)

以上是关于插入后 Knex 解析空集的主要内容,如果未能解决你的问题,请参考以下文章

通过 knex 插入虚假数据

使用 Knex.js 进行多行插入

Knex 不返回插入 ID

使用 Knex 和 PG 插入多行

仅当使用 knex 唯一时才插入

Knex NodeJS 并插入数据库