2017-10-23 1 views
0

Wie kann ich eine Antwort mit einer In-Memory-DB streamen?NodeJS - Wie kann ich eine Antwort mit einer In-Memory-DB streamen?

Ich benutze Loki JS als eine im Speicher DB. Es gibt eine bestimmte Ressource, wo ich den gesamten Inhalt einer Tabelle zurückgeben muss (kann nicht paginiert werden), und diese Tabelle kann bis zu 500.000 Elemente oder so wachsen, was ungefähr 300 MB ist.

In anderen Fällen habe ich fs.createReadStream verwendet, um eine Datei zu erhalten und es zurück an den Benutzer zu streamen:

fs.createReadStream('zips.json') 
    .on('data', function() { 
    res.write(...) 
    }) 
    .on('end', function() { 
    res.end(); 
    }) 

Diese große für große Dateien gearbeitet hat, aber wie kann ich etwas Gleichwertiges ein mit im Speicher DB?

const items = lokiDb.addCollection('items'); 
items.insert('a bunch of items ...'); 

// I would now like to stream items via res.write 
res.write(items) 

Derzeit res.write(items) werden Speicherprobleme verursachen, da Knoten versucht, die gesamte Antwort auf einmal zurückzukehren.

Antwort

0

Soweit ich das beurteilen kann, gibt es in Loki keinen eigenen Stream-Provider, obwohl ich ihn vielleicht verpasst habe. Was können Sie stattdessen tun möchte, ist mit dem ‚Einfügen‘ Ereignis auf der Sammlung hören und schreiben, dass, wie so:

const items = lokiDb.addCollection('items'); 
items.on('insert', (results) => { 
    res.write(results); 
}); 

items.insert('a bunch of items ...'); 
0

Wenn ich richtig bin, im Grunde Ihr Problem ist, dass readStreams nur aus Dateien lesen und dass Sie aus einer speicherinternen Datenstruktur lesen möchten. Eine Lösung könnte sein, eigene Readstream-Klasse zu definieren, leicht den Prototyp stream.Readable._read Verfahren modifiziert:

var util = require('util'); 
var stream = require('stream'); 

"use strict"; 
var begin=0, end=0; 
var options = { 
    highWaterMark: 16384, 
    encoding:  null, 
    objectMode:  false 
}; 

util.inherits(InMemoryStream, stream.Readable); 

function InMemoryStream(userDefinedOptions, resource){ 

    if (userDefinedOptions){ 
     for (var key in userDefinedOptions){ 
      options.key = userDefinedOptions[key]; 
     } 
    } 

    this.resource = resource; 
    stream.Readable.call(this, options); 
} 


InMemoryStream.prototype._read = function(size){ 

    end += size; 
    this.push(this.resource.slice(begin, end)); 
    begin += size; 

    } 

exports.InMemoryStream = InMemoryStream;  
exports.readStream = function(UserDefinedOptions, resource){ 
    return new InMemoryStream(UserDefinedOptions, resource); 
} 

Sie wandeln Ihre in-memory Datenstruktur (in dem folgenden Beispiel ein Array) auf eine Readstream und Rohr dies bis zu einem writeStream, wie folgt:

"use strict"; 

var fs = require('fs'); 
var InMemoryStream = require('/home/regular/javascript/poc/inmemorystream.js'); 

var stored=[], writestream, config={}; 

config = { 
    encoding: null, 
    fileToRead: 'raphael.js', 
    fileToWrite: 'secondraphael.js' 
} 

fs.readFile(config.fileToRead, function(err, data){ 
    if (err) return console.log('Error when opening file', err); 
    stored = data; 

    var inMemoryStream = InMemoryStream.readStream({encoding: config.encoding}, stored); 
    writestream = fs.createWriteStream(config.fileToWrite); 
    inMemoryStream.pipe(writestream); 

    inMemoryStream.on('error', function(err){ 
     console.log('in memory stream error', err); 
    }); 


}); 
+0

Sorry, dummes Beispiel; dachte nicht gerade: natürlich wird gespeichert einfach ein Puffer. Ändern Sie die push() im Prototyp wie folgt und Sie sollten in Ordnung sein, für String-basierte Daten mindestens: this.push (this.resource.join ('') .slice (Beginn, Ende)); – mycena

Verwandte Themen