0

I am using pg-promise.

I am having an issue trying to insert the following Javascript array:

[ { email: 'test1@gmail.com', password: 'test2' },
  { email: 'tes2t@gmx.com', password: 'test'3 },
  { email: 'test4@gmail.com', password: 'test4' },
  { email: 'test4@yahoo.com.ar', password: 'test5' }]

Using the following:

async function insertDB(data){
  const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});
  console.log(data)
  const query = pgp.helpers.insert(data, cs);

  db.none(query)
      .then(data => {
          logger.info(" Query success: ", data);
  })
  .catch(error => {
      logger.warn(" Query error: ", error);
  });
}

and I get

UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.

**data.password = undefined**
**data[0] = { email: 'test1@gmail.com', password: 'test2' }**

How can I insert this data into my postgresdb?

Sledro
  • 127
  • 1
  • 12
  • Side note 1: Never store passwords in cleartext in the database. In fact, never store passwords in the database full stop. (Store appropriately-salted hashes instead.) – T.J. Crowder Feb 26 '19 at 11:14
  • Side note 2: Why are you using `then` and `catch` in an `async` function? The point of `async` functions is that you can use `await` and logical-flow structures like `try`/`catch`. – T.J. Crowder Feb 26 '19 at 11:15
  • It seems fairly clear from the error that one of the entries in `data` doesn't have a property called `password` (despite your array shown at the top having a password on all of its objects). – T.J. Crowder Feb 26 '19 at 11:18
  • Side note 3: That's not a "Javascript JSON array". It's just an array. JSON is a *textual notation* for data exchange. [(More here.)](http://stackoverflow.com/a/2904181/157247) If you're dealing with JavaScript source code, and not dealing with a *string*, you're not dealing with JSON. – T.J. Crowder Feb 26 '19 at 11:18
  • 1
    @T.J.Crowder Thank you! The passwords won't be in clear text, it's just for the purpose of the demo.Re async: I just took that example from the pg-promise docs and added it to my code, thanks for the heads up though I didn't know that, will fix. – Sledro Feb 26 '19 at 11:20
  • 1
    Good point also on note 3, thanks again will update the question. – Sledro Feb 26 '19 at 11:23
  • @T.J.Crowder Do you know how I can let it continue with the insert if a password is missing? – Sledro Feb 26 '19 at 11:40
  • @Sledro What do you want to insert in place of a missing password? – vitaly-t Feb 26 '19 at 11:45
  • Just prefilter the data: `data = data.filter(({email, password}) => email && password);` That will create a new array containing only the objects from the original array that have non-blank `email` and `password` properties. https://jsfiddle.net/tjcrowder/3wLk9n46/ (There I'm assuming you don't want to insert that record at all.) – T.J. Crowder Feb 26 '19 at 11:46
  • Cheers T.J! This filter method worked nicely also! – Sledro Feb 26 '19 at 11:53

1 Answers1

0
// should create columnsets only once:
const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});

function insertDB(data) {

  // wrapping it into a function is safer, for error-reporting via query methods:
  const query = ()=> pgp.helpers.insert(data, cs);

  db.none(query)
      .then(data => {
          // data = null always here, no point displaying it
          logger.info('Query success:', data);
  })
  .catch(error => {
      logger.warn('Query error:', error);
  });
}

And your function doesn't need async in this case.

UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.

You are confusing the JavaScript compiler, declaring the function as async, and then throwing an error synchronously while generating the insert, due to missing property password.

And if you want to insert some records without password, with null, for example, define your columnset like this:

const cs = new pgp.helpers.ColumnSet([
    'email',
    {name: 'password', def: null}
], {table: 'users'});

Other than that, type ColumnSet is ultimately flexible, see the documentation for each contained Column.

EXTRA

And if you want to use server-side DEFAULT value for missing passwords, you can provide it, with the help of Custom Type Formatting:

const DEFAULT = {rawType: true, toPostgres: ()=> 'DEFAULT'};

And then your password column can be defined like this:

{name: 'password', def: DEFAULT}

And there are many alternatives, with properties init and mod supported by Column.

vitaly-t
  • 24,279
  • 15
  • 116
  • 138