Express/node-postgres передает объект с несколькими значениями для вставки запроса

Я сериализую форму и отправляю с помощью jQuery AJAX данные на экспресс-маршрут:

Объект, отправленный как arrobj, например:

{ 
  col1: [ 'one', 'two', 'three' ],
  col2: [ 'foo', 'bar', 'baz' ]
}

В маршруте у меня есть функция, которая создает параметризованную строку запроса следующим образом:

function create_insert_SQL(obj, table, returnid) {
    // Loop through OBJ and extract column names
    var cols = ''; // Store column names
    var params = ''; // Store Parameter references eg. $1, $2 etc
    var count = 1;
    for(var p in obj) {
        cols += p + ",";
        params += "$" + count + ",";
        count++;
    };
    var strSQL = "INSERT INTO " + table + " (";
    strSQL += cols.substr(0, cols.length - 1);
    strSQL += ') VALUES (';
    strSQL += params.substr(0, params.length - 1)
    strSQL += ') returning ' + returnid + ' as id';
    return strSQL;
}

Это вернет insert into mytable (col1,col2) values ($1, $2);

После создания строки запроса я запускаю запрос на вставку в node-postgres, передавая объект:

db.query(SQL, arrobj, function (err, result) {
    if (err) {
        res.send(err)
    } else {
        res.send(result.rows[0].id.toString()) // return the inserted value
    }
});

Для одиночных значений в каждом ключе все работает нормально и данные вставляются в таблицу корректно.

Как я могу запустить запрос на вставку для каждого значения ключей?

Пример:

insert into table (col1, col2) values ('one', 'foo');
insert into table (col1, col2) values ('two', 'bar');
insert into table (col1, col2) values ('three', 'baz');

person Fabrizio Mazzoni    schedule 05.03.2017    source источник
comment
Не делайте этого вручную, это очень подвержено ошибкам. Вместо этого см. Многострочная вставка с помощью pg-promise.   -  person vitaly-t    schedule 06.03.2017


Ответы (1)


Первая и самая сложная часть — инвертировать структуру вашего объекта, чтобы вы могли вставлять строки. Посмотрите приведенный ниже фрагмент и запустите его, чтобы увидеть, что произойдет.

После этого вы можете перебирать столбцы (для .. in, как у вас уже есть), чтобы получить часть столбцов INSERT INTO, и перебирать строки нового объекта, чтобы получить часть значений. Это должно быть достаточно легко, дайте мне знать, если вам нужна помощь.

var obj = { 
  col1: [ 'one', 'two', 'three' ],
  col2: [ 'foo', 'bar', 'baz' ],
  col3: [ '1', '2', '3' ]
}

//console.log(obj);

var invert = function (obj) {

  var new_obj = [];
  
  // iterate over props
  for (var prop in obj) {
    // iterate over columns
    for(var i=0;i<obj[prop].length;i++) {
    // if a row exists, assign value to it
     if (new_obj[i]) {
      new_obj[i][prop] = obj[prop][i];
     } else {
     // if it doesn't, create it
      var row = {};
      row[prop] = obj[prop][i];
      new_obj.push(row);
     }
    }
  }

  return new_obj;
};

var bulkStatement = function (table, rows) {
  var params = [];
  var chunks = [];
  var statement = 'INSERT INTO ' + table + '(';
  
  for (var prop in rows[0]) {
    statement += prop + ',';
  }
  
  statement = statement.slice(0,-1) + ') VALUES ';
  
  for(var i = 0; i < rows.length; i++) {
    var row = rows[i];
    var valueClause = [];
    for (var prop in row) {
      params.push(row[prop]);
      valueClause.push('$' + params.length);
    }
    chunks.push('(' + valueClause.join(', ') + ')');
  }

  return {
    text: statement + chunks.join(', '),
    values: params
  }
};

var inverted = invert(obj);

console.log(bulkStatement('tableName', inverted));

person paqash    schedule 05.03.2017
comment
Да, это путь. Единственная проблема заключается в том, что ключу нового объекта присваивается серийное значение, а не имя исходного объекта. Например, 0,1,2 вместо col1, col2 - person Fabrizio Mazzoni; 06.03.2017
comment
Я также добавил функцию генерации SQL, см. редактирование - person paqash; 06.03.2017
comment
@FabrizioMazzoni, ты смог заставить это работать таким образом? - person paqash; 07.03.2017