如何在 Node.JS 中进行多个查询(构建数据库)?

Posted

技术标签:

【中文标题】如何在 Node.JS 中进行多个查询(构建数据库)?【英文标题】:How can I do Multiple Queries (build out a DB) in Node.JS? 【发布时间】:2015-08-12 19:07:39 【问题描述】:

对 node.js 来说真的很新,对 PostgreSQL 来说相对较新。由于某种原因,这只会创建第一个表,而不是第二个。我可能完全做错了。我似乎找不到任何足够相似的代码示例来推断答案。我想创建两个表。看来我只能运行一个查询,仅此而已。不再。建议我的连接在第二个可以执行之前结束。我不知道为什么。在十几个不同的 Google 搜索中,我找不到一个这样做的例子。

var client = new pg.Client(connectionString);
client.connect();
var query = client.query('CREATE TABLE preferences(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, preferred BOOLEAN)');
client.query('CREATE TABLE foods(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, type VARCHAR(40) not null, spicy BOOLEAN, spiciness VARCHAR(10)');
query.on('end', function()  client.end(); );

我怀疑我是否可以只执行另一个 client.query 并在最后执行它。我从教程中取出了这个例子,但是我添加了第二个表。所以我只是在玩它,并尝试通过这个测试在这里学习。

只是为了说明我的最终目标:我想最终创建一个完整的脚本来构建完全包含所有必要表和数据的数据库。

无论我尝试什么都会出错:

$ 节点模型/database.js 事件.js:85 投掷者; // 未处理的“错误”事件 ^ 错误:输入末尾的语法错误 在 Connection.parseE (~/Documents/test01/node_modules/pg/lib/connection.js:534:11) 在 Connection.parseMessage (~/Documents/test01/node_modules/pg/lib/connection.js:361:17) 在套接字。 (~/Documents/test01/node_modules/pg/lib/connection.js:105:22) 在 Socket.emit (events.js:107:17) 在 readableAddChunk (_stream_readable.js:163:16) 在 Socket.Readable.push (_stream_readable.js:126:10) 在 TCP.onread (net.js:538:20)

【问题讨论】:

您只等待其中一个结束,而不是另一个结束,因此您可能提前结束了连接。 从我收集到的内容(那里的教程很糟糕),query.on('end'... 部分结束了与数据库的连接。它得到 throw er; // 未处理的 'error' 事件在回复中。我现在仍然很困惑。 query.on(type, handler) 为传入的类型添加事件处理程序,在本例中为“end”。当您附加到的查询发生该事件时,处理程序将触发。因此,处理程序会在第一个查询完成时触发,这很可能在第二个查询完成之前。 是的,我还是被难住了。 @NathanMcKaskle 你从来没有接受过任何答案? 【参考方案1】:

您正在尝试执行两个异步操作,因此您需要等到两个操作都完成后才能继续。一种方法是使用计数变量。

var client = new pg.Client(connectionString);
client.connect();
var query1 = client.query('CREATE TABLE preferences(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, preferred BOOLEAN)');
var query2 = client.query('CREATE TABLE foods(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, type VARCHAR(40) not null, spicy BOOLEAN, spiciness VARCHAR(10))');
var count = 2;

function endHandler () 
   count--; // decrement count by 1
   if (count === 0) 
       // two queries have ended, lets close the connection.
       client.end();
   


query1.on('end', endHandler);
query2.on('end', endHandler);

请注意,在这种情况下,您可能只是将这两个语句合并为一个,假设 postgres 支持该功能并且您的系统中启用了该功能。

client.query('CREATE TABLE preferences(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, preferred BOOLEAN);CREATE TABLE foods(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, type VARCHAR(40) not null, spicy BOOLEAN, spiciness VARCHAR(10));')

【讨论】:

(count === 0) 三个等号不是指类型等价吗? 是的,这个似乎不起作用,同样的错误:events.js:85 throw er; // 未处理的“错误”事件 三个= 是类型和值。我通常总是使用 3。 你能给出完整的堆栈跟踪吗? $ node models/database.js events.js:85 throw er; // 未处理的 'error' 事件 ^ 错误:在 Connection.parseE (~/Documents/test01/node_modules/pg/lib/connection.js:534:11) 在 Connection.parseMessage (~/Documents/ test01/node_modules/pg/lib/connection.js:361:17) 在 Socket. (~/Documents/test01/node_modules/pg/lib/connection.js:105:22) 在 Socket.emit (events. js:107:17) 在 Socket.Readable.push (_stream_readable.js:126:10) 在 TCP.onread (net.js:538:20) 的 readableAddChunk (_stream_readable.js:163:16) 【参考方案2】:

您需要管理多个“查询”变量。在您的情况下,代码可能如下所示:

    var client = new pg.Client(connectionString);
        client.connect();
    var queryPreferences = client.query('CREATE TABLE preferences(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, preferred BOOLEAN)');

    var foods = function()  
        var queryFoods = client.query('CREATE TABLE foods(id SERIAL PRIMARY KEY, food VARCHAR(40) not null, type VARCHAR(40) not null, spicy BOOLEAN, spiciness VARCHAR(10)');
        queryFoods.on('end', function()  client.end(); );
    

    queryPreferences.on('end', foods);

这样,您将运行第二个查询,直到完成第一个查询,然后关闭连接。

【讨论】:

我不确定你的答案的一件事是“结束”事件是否类似于承诺,如果结束事件已经发生,它会立即触发任何新事件,或者它会什么都不做,因为自定义处理程序以来没有发生任何事件。但是,在这种情况下,我认为这并不重要,因为client 可能会以串行方式而不是并行方式发送请求,或者数据库将以串行方式而不是并行方式响应。 谢谢@KevinB,是的,这就是重点。并行发送请求,因此您只需担心在最后一个请求结束时关闭连接。请注意,第二个事件 end 它订阅了 queryFoods 发射器。 对,我担心的是,如果 queryFoods 先完成呢?但就像我说的,这可能不是问题,因为这是一个数据库连接,除非使用单独的连接,否则它通常是先进先出的。 哦,现在我明白了,我和你在一起。可能不是问题,但可以确定我编辑了我的答案。我认为这可以让我对请求的顺序感到平静。 和这个一样:events.js:85 throw er; // 未处理的 'error' 事件——显然我在这里做了一些非常新的事情。不确定是否有人创建了一个 JS 来创建一堆表。我想最终创建一个完整的脚本来构建完全包含所有必要表和数据的数据库。【参考方案3】:

最好的方法是将所有请求放入一个事务中并在同一个连接中执行。

在pg-promise 的帮助下,您可以这样做:

var pgp = require('pg-promise')(/*options*/);
var db = pgp(connection);

db.tx(t => 
        return t.batch([
            t.none('CREATE TABLE preferences(id SERIAL, etc...'),
            t.none('CREATE TABLE foods(id SERIAL PRIMARY KEY, etc...')
        ]);
    )
    .then(data => 
        // success;
    )
    .catch(error => 
        console.log(error); // print error;
    );

更好的是,将所有 SQL 放入外部 SQL files,库对此提供自动支持。

【讨论】:

是的,你的图书馆很棒;)

以上是关于如何在 Node.JS 中进行多个查询(构建数据库)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MySql 中使用 sequelize 运行多个原始查询?

Node.js MySql如何知道用户ID以在登录后的查询中使用它

如何评价Uber不用Node.js,而用Go语言构建地理查询服务?

如何在 Node.js 和 Express 上的同一个 .ejs 文件上呈现 MySQL 查询的多个结果?

使用 Oracle 程序 - Node.js Knex.js

如何从Google Cloud Function(Cheerio,Node.js)发出多个http请求