Cómo hacer una conexión a Postgres a través de Node.js

123

Me encuentro tratando de crear una base de datos postgres, así que instalé postgres e inicié un servidor initdb /usr/local/pgsql/data, luego comencé esa instancia postgres -D /usr/local/pgsql/dataahora, ¿cómo puedo interactuar con esto a través del nodo? Por ejemplo, qué sería connectionstring, o cómo puedo averiguar qué es.

Doboy
fuente

Respuestas:

313

Aquí hay un ejemplo que usé para conectar node.js a mi base de datos Postgres.

La interfaz en node.js que utilicé se puede encontrar aquí https://github.com/brianc/node-postgres

var pg = require('pg');
var conString = "postgres://YourUserName:YourPassword@localhost:5432/YourDatabase";

var client = new pg.Client(conString);
client.connect();

//queries are queued and executed one after another once the connection becomes available
var x = 1000;

while (x > 0) {
    client.query("INSERT INTO junk(name, a_number) values('Ted',12)");
    client.query("INSERT INTO junk(name, a_number) values($1, $2)", ['John', x]);
    x = x - 1;
}

var query = client.query("SELECT * FROM junk");
//fired after last row is emitted

query.on('row', function(row) {
    console.log(row);
});

query.on('end', function() {
    client.end();
});



//queries can be executed either via text/parameter values passed as individual arguments
//or by passing an options object containing text, (optional) parameter values, and (optional) query name
client.query({
    name: 'insert beatle',
    text: "INSERT INTO beatles(name, height, birthday) values($1, $2, $3)",
    values: ['George', 70, new Date(1946, 02, 14)]
});

//subsequent queries with the same name will be executed without re-parsing the query plan by postgres
client.query({
    name: 'insert beatle',
    values: ['Paul', 63, new Date(1945, 04, 03)]
});
var query = client.query("SELECT * FROM beatles WHERE name = $1", ['john']);

//can stream row results back 1 at a time
query.on('row', function(row) {
    console.log(row);
    console.log("Beatle name: %s", row.name); //Beatle name: John
    console.log("Beatle birth year: %d", row.birthday.getYear()); //dates are returned as javascript dates
    console.log("Beatle height: %d' %d\"", Math.floor(row.height / 12), row.height % 12); //integers are returned as javascript ints
});

//fired after last row is emitted
query.on('end', function() {
    client.end();
});

ACTUALIZACIÓN: - LA query.onfunción ahora está en desuso y, por lo tanto, el código anterior no funcionará según lo previsto. Como solución para este vistazo a: - query.on no es una función

Kuberchaun
fuente
24
Ahora ese es el tipo de ejemplo que me gusta ver. Claro e inclusivo de suficiente código. Gracias JustBob
Stradas
1
¿Qué agregaste en tu pg_hba.conf para permitir conexiones desde node.js? Gracias
Marius
3
host all all 0.0.0.0/0 md5 Esta entrada, si recuerdo bien, permitirá que cualquier IP se conecte. Tenga en cuenta que esto no es específico de nodo, sino específico de PostgreSQL. También en postgresql.conf tengo listen_addresses = '*'. Para configuraciones de producción, lea los documentos para asegurarse de no abrir agujeros en ningún lado. Lo uso en mi configuración de desarrollo, así que estoy bien para permitir que cualquier máquina se conecte.
Kuberchaun
1
Los parámetros de conString explicados son geniales, y justo lo que estaba buscando. ¡Gracias!
nelsonenzo
33

Un enfoque moderno y simple: pg-promise :

const pgp = require('pg-promise')(/* initialization options */);

const cn = {
    host: 'localhost', // server name or IP address;
    port: 5432,
    database: 'myDatabase',
    user: 'myUser',
    password: 'myPassword'
};

// alternative:
// var cn = 'postgres://username:password@host:port/database';

const db = pgp(cn); // database instance;

// select and return a single user name from id:
db.one('SELECT name FROM users WHERE id = $1', [123])
    .then(user => {
        console.log(user.name); // print user name;
    })
    .catch(error => {
        console.log(error); // print the error;
    });

// alternative - new ES7 syntax with 'await':
// await db.one('SELECT name FROM users WHERE id = $1', [123]);

Vea también: Cómo declarar correctamente su módulo de base de datos .

vitaly-t
fuente
Si bien este enlace puede responder la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden volverse inválidas si la página vinculada cambia.
arulmr
1
En un mundo ideal, sí, y aún así, la respuesta aceptada aquí, como puede ver arriba, solo el enlace también. Igual que allí, sería demasiado hacer un resumen de la información que proporciona el enlace, y teniendo en cuenta que ambos enlaces se dan a los repositorios públicos de GitHub, las posibilidades de que se bloqueen no son más que las posibilidades de que StackOverflow se bloquee. .
vitaly-t
Tal vez solo proporcione un ejemplo simple de usarlo para algo muy básico, que solo debería ocupar unas pocas líneas, pero sería suficiente para no hacerlo solo de enlace.
Qantas 94 Heavy
@ Qantas94Heavy, y lo acabo de hacer, aplazar el voto
negativo
@ vitaly-t: Alguien probablemente marcó la publicación como "muy baja calidad", lo que da un voto negativo automático si la publicación se edita o elimina antes de que se maneje la bandera.
Qantas 94 Heavy
12

Solo para agregar una opción diferente: uso Node-DBI para conectarme a PG, pero también debido a la capacidad de hablar con MySQL y sqlite. Node-DBI también incluye la funcionalidad para construir una declaración de selección, que es útil para hacer cosas dinámicas sobre la marcha.

Muestra rápida (utilizando información de configuración almacenada en otro archivo):

var DBWrapper = require('node-dbi').DBWrapper;
var config = require('./config');

var dbConnectionConfig = { host:config.db.host, user:config.db.username, password:config.db.password, database:config.db.database };
var dbWrapper = new DBWrapper('pg', dbConnectionConfig);
dbWrapper.connect();
dbWrapper.fetchAll(sql_query, null, function (err, result) {
  if (!err) {
    console.log("Data came back from the DB.");
  } else {
    console.log("DB returned an error: %s", err);
  }

  dbWrapper.close(function (close_err) {
    if (close_err) {
      console.log("Error while disconnecting: %s", close_err);
    }
  });
});

config.js:

var config = {
  db:{
    host:"plop",
    database:"musicbrainz",
    username:"musicbrainz",
    password:"musicbrainz"
  },
}
module.exports = config;
mlaccetti
fuente
Hola, mlaccetti, tengo un problema similar al intentar conectar y ejecutar pruebas en una base de datos SQLite3. Estoy siguiendo un tutorial con instrucciones para usar DBWrapper, por eso me estoy comunicando contigo. Mi pregunta está aquí: stackoverflow.com/q/35803874/1735836
Patricia
Node-DBI ha sido abandonado desde hace mucho tiempo y ya no es compatible.
vitaly-t
2

Una solución puede ser el uso poolde clientes como el siguiente:

const { Pool } = require('pg');
var config = {
    user: 'foo', 
    database: 'my_db', 
    password: 'secret', 
    host: 'localhost', 
    port: 5432, 
    max: 10, // max number of clients in the pool
    idleTimeoutMillis: 30000
};
const pool = new Pool(config);
pool.on('error', function (err, client) {
    console.error('idle client error', err.message, err.stack);
});
pool.query('SELECT $1::int AS number', ['2'], function(err, res) {
    if(err) {
        return console.error('error running query', err);
    }
    console.log('number:', res.rows[0].number);
});

Puede ver más detalles sobre este recurso .

Dios mio
fuente
no usaste 'config'.
LEMUEL ADANE
1

Slonik es una alternativa a las respuestas propuestas por Kuberchaun y Vitaly.

Slonik implementa un manejo de conexión seguro ; crea un grupo de conexión y la apertura / manejo de la conexión se maneja por usted.

import {
  createPool,
  sql
} from 'slonik';

const pool = createPool('postgres://user:password@host:port/database');

return pool.connect((connection) => {
  // You are now connected to the database.
  return connection.query(sql`SELECT foo()`);
})
  .then(() => {
    // You are no longer connected to the database.
  });

postgres://user:password@host:port/database es su cadena de conexión (o más canónicamente, un URI o DSN de conexión).

El beneficio de este enfoque es que su script asegura que nunca deje accidentalmente conexiones colgantes.

Otros beneficios por usar Slonik incluyen:

Gajus
fuente
0

También podemos usar postgresql-easy . Está construido en node-postgres y sqlutil . Nota: pg_connection.js y your_handler.js están en la misma carpeta. db.js está en la carpeta de configuración colocada.

pg_connection.js

const PgConnection = require('postgresql-easy');
const dbConfig = require('./config/db');
const pg = new PgConnection(dbConfig);
module.exports = pg;

./config/db.js

module.exports =  {
  database: 'your db',
  host: 'your host',
  port: 'your port',
  user: 'your user',
  password: 'your pwd',
}

your_handler.js

  const pg_conctn = require('./pg_connection');

  pg_conctn.getAll('your table')
    .then(res => {
         doResponseHandlingstuff();
      })
    .catch(e => {
         doErrorHandlingStuff()     
      })
Naveen Karnam
fuente