2017-05-22 3 views
0

In Javascript gibt der Neo4j Bolt-Treiber {low: lll, high: hhh} Objekte anstelle von Ganzzahlen zurück. Super für 64-Bit-Ganzzahlen, aber es wirft ein paar Probleme in meinen bescheidenen Javascript-Web-Apps auf. Es scheint nun, dass ich alle meine Front-Scripts durchgehen und nach dem Typ "Objekt" suchen muss, wo immer ich ein Datum oder eine Nummer vom Server bekomme, und dann entweder die Konvertierungsroutinen des Bolt-Treibers (nachdem ich den Treiber geladen habe) der Kunde), oder bauen Sie mein eigenes. Nachdem ich es zu lange verschoben habe, habe ich gerade von neo4j 2.3 auf 3.2 geupdated und bin hüfthoch in der Konvertierung zu Bolt, aber die volle Bedeutung dieses kleinen Addendums in den Bolt-Dokumenten über Ganzzahlen beginnt langsam zu sinken.Neo4j Bolt-Treiber, Javascript, Ganzzahlen verarbeiten

Also Neo4j Leute: ist dieser Bolt-Treiber die Mühe wert? Ist der Odd-Ball-Ansatz zur Bereitstellung von Ganzzahlen stabil oder wird er zu einem bestimmten Zeitpunkt korrigiert - z. B. durch eine Anweisung an den Fahrer, wie Zahlen ausgegeben werden sollen? Gibt es einen Trick, um damit umzugehen, von dem ich nichts weiß? Sollte ich zurückgehen und zu Akeems Node-Neo4j-Treiber zurückkehren?

Danke für alle Einsichten!

+0

Nachtrag: Die Frage stellt sich in der Neo4j-Javascript-Treiber Probleme Liste nach oben (153, 122, 106, etc.). Die Methoden des Bolt-Treibers (InSafeRange, int usw.) werden als eine Auflösung dargestellt. Dies bedeutet jedoch, dass codierte Konvertierungen gegen eine feste Menge von Datenentitäten durchgeführt werden müssen. Normalerweise sollte der Treiber eine Direktive verwenden und 64-Bit-Zahlen nur als letztes Mittel in {high: low:} Objekte konvertieren. Konvertieren aller Integer in Objekte und dann erfordert einen Server zu hart-Code-Konvertierung von meisten in JS-Nummern ist eine riesige Zeitverschwendung. Die Frage ist, werden sie es beheben? Wann? – HieroB

+0

Ich denke, es wäre weitaus verwirrender, wenn der Treiber nur einige Zahlen konvertiert, um das Integer-Objekt zu verwenden (z. B. {high: low:}). Der Benutzer des Treibers müsste dann jeden Wert prüfen, um zu sehen, ob er konvertiert wurde oder nicht, was eine Menge Aufwand ist. Besser konsistent sein. –

Antwort

1

Neo4j geht eindeutig in Richtung der Verwendung des BOLT-Protokolls und der zugehörigen Treiber für die Interaktion mit der Datenbank. Das Protokoll selbst gibt bis zu 64-Bit-Ganzzahlen zurück (https://boltprotocol.org/v1/#ints).

Javascript hat jedoch nur einen Zahlentyp, der Fließkomma ist, und wird nur ganze Zahlen genau auf 53 Bits (http://ecma262-5.com/ELS5_HTML.htm#Section_8.5) darstellen.

Damit JavaScript-Code Ganzzahlen verarbeiten kann, die größer als 53 Bit sind, müssen diese Zahlen in einen anderen Typ codiert werden. Der Neo4j-Javascript-Treiber hat das Integer-Objekt für diesen Zweck eingeführt (https://neo4j.com/docs/api/javascript-driver/current/class/src/v1/integer.js~Integer.html). Glücklicherweise enthält dieses Objekt zahlreiche Hilfsmethoden, einschließlich toInt() und toNumber() für die Konvertierung zurück zu regulären Javascript-Typen (mit Verlust der Genauigkeit, sollte die Ganzzahl größer als 2^53, die mit inSafeRange() überprüft werden kann).

+0

Dank Chris, ich bleibe bei Bolt, aber dieser Ansatz: a) bricht die Datentrennung, da es fest programmierte Utility-Methoden pro Property benötigt; b) verschwendet Zeit, da mein Front-Line-Server nun alle Eingänge in Objekte umwandelt, diese dann alle testet und konvertiert; c) kontaminiert den clientseitigen Code, da viele dieser Objekte an den Client übergeben werden (der Client muss also auch den Treiber laden oder alternative Konvertierungsmethoden bereitstellen). In einem JS-Treiber würde ich eine optionale Anweisung bevorzugen, wenn ich die Abfrage ausführe, so dass ich dem Treiber sagen kann, dass er JS-Nummern abschneiden und nicht in Objekte konvertieren soll. – HieroB

+0

Ich überlasse es dem Neo4j-Team, auf ihr Github-Problem zu antworten, wenn sie eine solche "fakultative Direktive" einführen möchten. Persönlich folge ich nicht deiner Argumentation. Der Neo4j-Server gibt die Ganzzahl bereits über Bolt als 64-Bit-Int zurück (https://boltprotocol.org/v1/#ints). Der Javascript-Treiber stellt das als zwei 32-Bit-Ints dar, um die 53-Bit-Beschränkung in Javascript zu umgehen. Wenn Ihr Code sicher davon ausgehen kann, dass keine Ints 53 Bit überschreiten, können Sie in eine normale JavaScript-Nummer konvertieren. Der Overhead von all dem sollte sehr, sehr minimal sein (Javascript ist sowieso nicht so effizient!). –

0

In Antwort auf meine Fragen:

a) Schraubeneinzieher ist eng gekoppelt mit Steckdosen und eigenes Protokoll (Danke Chris für den Zeiger auf Neo4j); daher denke ich, dass es sich lohnt, anzugehen; Es gibt jedoch einige Probleme, da Sie tatsächlich Konvertierungsroutinen an jedem Punkt hinzufügen müssen, an dem eine Ganzzahl von der Datenbank in allen Server- und Clientskripten zurückgegeben wird. Wenn Sie keine 64-Bit-Integer verwenden, konvertiert der Treiber alle Ints in Objekte und Sie müssen sie dann alle wieder zurück konvertieren, so dass es auf dem Server etwas mehr Gewicht hat.

b) Ich habe ein Problem mit neo4j-drivers-Entwicklern angesprochen und eine Option für die 'run' -Methode angefordert, die dazu führen würde, dass der Treiber Javascript-Nummern bis 2^53 zurückgibt oder eine Exception für Out-of-Bound-Ganzzahlen auslöst ; Dies würde die Aktualisierung erleichtern und den Server in Fällen wie meiner sauberer laufen lassen; Diese Anfrage steht noch aus.

c) Wie für Shortcuts habe ich Folgendes verwendet; hoffe, dass sie jemandem helfen:

1) Um zu vermeiden, dass ich den neoj4-driver/library auf den Client laden muss, habe ich die Konvertierungsroutine des Treibers kopiert. Ich füge die folgenden 2 Zeilen meinen clientseitigen Skripten hinzu; dann kann ich bolt_num (n) nennen zu Rufnummern konvertieren:

const TWO_PWR_32_DBL = (1 << 16) * (1 << 16); 
const bolt_num = function(n){ return typeof n == 'object'? n.hasOwnProperty('low')? n.high * TWO_PWR_32_DBL + (n.low >>> 0) : n : n; } 

2) Nach 50 oder so Fehler zu ändern, ich in Patching die Fahrer betrachtete js Zahlen zurückzukehren. Der temporäre Fix unten fängt keine Out-of-Bounds ein, aber wie gesagt, ich brauche das nicht. Änderungen gelten für den neo4j-javascript-Treiber (v1.4) in einer Datei: node_modules/neo4j-driver/internal/packstream.js, beginnend um Linie 400 oder so. Meine 5 Ersatzlinien sind kommentiert als // neu; Linien, die sie ersetzen, sind auskommentiert. In meinem Anwendungscode funktionieren die Änderungen, die ich bereits vorgenommen habe, weiterhin - die Neo4j-Treiberkonvertierungen akzeptieren reine Ganzzahlen. So kann ich viel schneller aufsetzen und die numerischen Konvertierungen in meinem eigenen Tempo hinzufügen - es sei denn, ich entscheide mich, einfach mit dem modifizierten Treiber zu bleiben, um meinen Knotenserver nicht zu verlangsamen.

key: "unpack", 
value: function unpack(buffer) { 
    var marker = buffer.readUInt8(); 
    if (marker == NULL) { 
    return null; 
    } else if (marker == TRUE) { 
    return true; 
    } else if (marker == FALSE) { 
    return false; 
    } else if (marker == FLOAT_64) { 
    return buffer.readFloat64(); 
    } else if (marker >= 0 && marker < 128) { 
    return marker; // new 
    //return (0, _integer.int)(marker); 
    } else if (marker >= 240 && marker < 256) { 
    return marker-256; // new 
    //return (0, _integer.int)(marker - 256); 
    } else if (marker == INT_8) { 
    return buffer.readInt8(); // new 
    //return (0, _integer.int)(buffer.readInt8()); 
    } else if (marker == INT_16) { 
    return buffer.readInt16(); // new 
    //return (0, _integer.int)(buffer.readInt16()); 
    } else if (marker == INT_32) { 
    return buffer.readInt32(); // new 
    //var b = buffer.readInt32(); 
    //return (0, _integer.int)(b); 
    } else if (marker == INT_64) { 
    var high = buffer.readInt32(); 
    var low = buffer.readInt32(); 
    var TWO_PWR_32_DBL = (1 << 16) * (1 << 16); // new 
    return high * TWO_PWR_32_DBL + (low >>> 0); // new 
    //return new _integer2.default(low, high); 
    } else if (marker == STRING_8) { 
Verwandte Themen