2017-06-27 8 views
1

Ich habe einen seltsamen Fehler mit NodeJS mit einem PostgreSQL und ich hoffe, Sie können mir vielleicht helfen.nodeJS Einfügen von Daten in PostgreSQL Fehler

Ich habe eine riesige Menge an Datensätzen, etwa 2 Millionen Einträge, die ich in meine DB einfügen möchte.

Ein Datum besteht aus 4 Säulen:

id: string, 
points: float[][] 
mid: float[] 
occurences: json[] 

I-Daten am Einsetzen in etwa so:

let pgp = require('pg-promise')(options); 
let connectionString = 'postgres://archiv:[email protected]:5432/fotoarchivDB'; 
let db = pgp(connectionString); 

cityNet.forEach((arr) => { 
    db 
    .none(
     "INSERT INTO currentcitynet(id,points,mid,occurences) VALUES $1", 
     Inserts("${id},${points}::double precision[],${mid}::double precision[],${occurences}::json[]",arr)) 
    .then(data => { 
     //success 
    }) 
    .catch(error => { 
     console.log(error); 
     //error 
    }); 
}) 

function Inserts(template, data) { 
    if (!(this instanceof Inserts)) { 
     return new Inserts(template, data); 
    } 
    this._rawDBType = true; 
    this.formatDBType = function() { 
    return data.map(d => "(" + pgp.as.format(template, d) + ")").join(","); 
}; 

Dies funktioniert genau aus für die ersten 309.248 Datenstücke, dann plötzlich nur Fehler aus mit dem folgenden für (wie es scheint) jede nächste Daten, die es versucht einzufügen:

{ error: syntax error at end of input 
at Connection.parseE (/home/christian/Masterarbeit_reworked/projekt/server/node_modules/pg-promise/node_modules/pg/lib/connection.js:539:11) 
at Connection.parseMessage (/home/christian/Masterarbeit_reworked/projekt/server/node_modules/pg-promise/node_modules/pg/lib/connection.js:366:17) 
at Socket.<anonymous> (/home/christian/Masterarbeit_reworked/projekt/server/node_modules/pg-promise/node_modules/pg/lib/connection.js:105:22) 
at emitOne (events.js:96:13) 
at Socket.emit (events.js:188:7) 
at readableAddChunk (_stream_readable.js:176:18) 
at Socket.Readable.push (_stream_readable.js:134:10) 
at TCP.onread (net.js:548:20) 
name: 'error', 
length: 88, 
severity: 'ERROR', 
code: '42601', 
detail: undefined, 
hint: undefined, 
position: '326824', 
internalPosition: undefined, 
internalQuery: undefined, 
where: undefined, 
schema: undefined, 
table: undefined, 
column: undefined, 
dataType: undefined, 
constraint: undefined, 
file: 'scan.l', 
line: '1074', 
routine: 'scanner_yyerror' } 

Die 'Position' -Eintrag ändert sich für jede iterierende Fehlermeldung.

Ich kann das wiederholen und es wird immer Fehler nach 309248 Einträge. Wenn ich versuche, weniger als 1000 Einträge einzufügen, tritt der Fehler nicht auf.

Das verwirrt mich wirklich. Ich dachte, dass PostgreSQL keine maximale Anzahl von Zeilen hat. Auch die Fehlermeldung hilft mir überhaupt nicht.

Gelöst Der Fehler wurde gefunden. In meinen Daten waren "Null" -Einträge, die hineingerutscht sind. Herausfiltern von Null-Daten ausgearbeitet. Ich werde die anderen Empfehlungen für das Einfügen von Daten ausprobieren, da der aktuelle Weg funktioniert, aber die Leistung ist sehr beschissen.

+0

Versuchen Sie, auf einmal 2 Millionen Datensätze einfügen? Die Node.js würde das nicht verarbeiten können. Die Inserts müssen richtig paginiert werden. Verwenden Sie diesen alten Ansatz nicht zum Generieren von Einfügungen, sondern verwenden Sie den hier gezeigten: https: // stackoverflow.com/questions/37300997/multi-row-insert-mit-pg-versprechen –

Antwort

1

Ich bin nicht sicher, aber es sieht aus wie Sie eine Eigenschaft falsche Datenstruktur auf dem letzten Element (309.249) und PostgreSQL kann nicht analysieren bekam

+0

tahts scheint richtig. irgendwie wurde das letzte Element 'null' Ich werde herausfinden, warum ein Null hinzugefügt wird, entfernen Sie es und versuchen Sie es erneut – Christian

+0

Sie hatten Recht. Es hat den Fehler behoben. Vielen Dank. – Christian

+0

Das ist großartig. Willkommen –

0

Ich bin der Autor von pg-promise. Ihr gesamter Ansatz sollte zu dem folgenden geändert werden.

Richtiger Weg massive Einsätze über pg-promise zu tun:

const pgp = require('pg-promise')({ 
    capSQL: true 
}); 

const db = pgp(/*connection details*/); 

var cs = new pgp.helpers.ColumnSet([ 
    'id', 
    {name: 'points', cast: 'double precision[]'}, 
    {name: 'mid', cast: 'double precision[]'}, 
    {name: 'occurences', cast: 'json[]'} 
], {table: 'currentcitynet'}); 

function getNextInsertBatch(index) { 
    // retrieves the next data batch, according to the index, and returns it 
    // as an array of objects. A normal batch size: 1000 - 10,000 objects, 
    // depending on the size of the objects. 
    // 
    // returns null when there is no more data left. 
} 

db.tx('massive-insert', t => { 
    return t.sequence(index => { 
     const data = getNextInsertBatch(index); 
     if (data) { 
      const inserts = pgp.helpers.insert(data, cs); 
      return t.none(inserts); 
     } 
    }); 
}) 
    .then(data => { 
     console.log('Total batches:', data.total, ', Duration:', data.duration); 
    }) 
    .catch(error => { 
     console.log(error); 
    }); 

UPDATE

Und wenn getNextInsertBatch nur die Daten asynchron bekommen, dann ein Versprechen von ihm zurück und aktualisieren Sie den sequence->source Rückruf entsprechend :

return t.sequence(index => { 
    return getNextInsertBatch(index) 
     .then(data => { 
      if (data) { 
       const inserts = pgp.helpers.insert(data, cs); 
       return t.none(inserts); 
      } 
     }); 
}); 

Weitere Links:

+0

wow, ich werde das ausprobieren und mein Feedback geben. – Christian

+0

@Christian mit dem richtigen Ansatz, der hier beschrieben wird, wäre es auch einfacher zu diagnostizieren und zu ändern, weil Typ 'ColumnSet' Sie alarmiert, wenn es auf ein' null' stößt. Plus die Leistung ist deutlich besser. –

+0

@Christian wie ist es gelaufen? ;) –

Verwandte Themen