Как передать результаты запросов MongoDB с помощью nodejs?
Я искал пример того, как я могу передать результат запроса MongoDB клиенту nodejs. Все решения, которые я нашел до сих пор, похоже, сразу читают результат запроса, а затем отправляют результат обратно на сервер.
Вместо этого я (очевидно) хотел бы предоставить обратный вызов методу запроса и вызвать MongoDB, когда доступен следующий фрагмент результирующего набора.
Я смотрел мангуст - должен ли я использовать другой драйвер?
Jan
Ответы
Ответ 1
Потоковая передача в Mongoose стала доступна в версии 2.4.0, которая появилась три месяца после того, как вы разместили этот вопрос:
Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
Более подробные примеры можно найти на странице .
Ответ 2
node-mongodb-driver
(базовый уровень, который использует каждый клиент mongoDB в nodejs), за исключением API-интерфейса курсора, который упоминается в других языках, имеет хороший API потока (# 458). К сожалению, я не нашел его в другом месте.
Обновление: есть документы и здесь.
Его можно использовать следующим образом:
var stream = collection.find().stream()
stream.on('error', function (err) {
console.error(err)
})
stream.on('data', function (doc) {
console.log(doc)
})
Он фактически реализует интерфейс ReadableStream, поэтому он имеет все полезные свойства (пауза/возобновление и т.д.)
Ответ 3
mongoose
на самом деле не является "драйвером", он фактически является оберткой ORM вокруг драйвера MongoDB (node-mongodb-native
).
Чтобы сделать то, что вы делаете, взгляните на метод драйвера .find
и .each
. Вот несколько примеров из примеров:
// Find all records. find() returns a cursor
collection.find(function(err, cursor) {
sys.puts("Printing docs from Cursor Each")
cursor.each(function(err, doc) {
if(doc != null) sys.puts("Doc from Each " + sys.inspect(doc));
})
});
Чтобы передать результаты, вы в основном заменяете эту функцию sys.puts
своей "потоковой" функцией. Не знаете, как вы планируете передавать результаты. Я думаю, вы можете сделать response.write() + response.flush()
, но вы также можете проверить socket.io
.
Ответ 4
Вот решение, которое я нашел (пожалуйста, поправьте меня всем, если это неправильный способ сделать это):
(Также извините за плохое кодирование - слишком поздно для меня сейчас, чтобы отменить это)
var sys = require('sys')
var http = require("http");
var Db = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Db,
Connection = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Connection,
Collection = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Collection,
Server = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Server;
var db = new Db('test', new Server('localhost',Connection.DEFAULT_PORT , {}));
var products;
db.open(function (error, client) {
if (error) throw error;
products = new Collection(client, 'products');
});
function ProductReader(collection) {
this.collection = collection;
}
ProductReader.prototype = new process.EventEmitter();
ProductReader.prototype.do = function() {
var self = this;
this.collection.find(function(err, cursor) {
if (err) {
self.emit('e1');
return;
}
sys.puts("Printing docs from Cursor Each");
self.emit('start');
cursor.each(function(err, doc) {
if (!err) {
self.emit('e2');
self.emit('end');
return;
}
if(doc != null) {
sys.puts("doc:" + doc.name);
self.emit('doc',doc);
} else {
self.emit('end');
}
})
});
};
http.createServer(function(req,res){
pr = new ProductReader(products);
pr.on('e1',function(){
sys.puts("E1");
res.writeHead(400,{"Content-Type": "text/plain"});
res.write("e1 occurred\n");
res.end();
});
pr.on('e2',function(){
sys.puts("E2");
res.write("ERROR\n");
});
pr.on('start',function(){
sys.puts("START");
res.writeHead(200,{"Content-Type": "text/plain"});
res.write("<products>\n");
});
pr.on('doc',function(doc){
sys.puts("A DOCUMENT" + doc.name);
res.write("<product><name>" + doc.name + "</name></product>\n");
});
pr.on('end',function(){
sys.puts("END");
res.write("</products>");
res.end();
});
pr.do();
}).listen(8000);
Ответ 5
Я сам изучал потоки mongodb, хотя у меня нет полного ответа, который вы ищете, у меня есть его часть. Вы можете настроить поток socket.io
это использует javascript socket.io и socket.io-streaming, доступные в NPM, также mongodb для базы данных, потому что использование базы данных 40-летнего возраста, которая имеет проблемы, является неправильным, время для модернизации также 40-летнего БД - это SQL, а SQL - нет делай потоки, насколько мне известно
Таким образом, хотя вы спрашивали только о данных, передаваемых с сервера на клиент, я также хочу, чтобы в ответе я получал информацию от клиента к серверу, потому что НИКОГДА не могу найти ее в любом месте при поиске, и я хотел настроить одно место с элементами отправки и получения через поток чтобы каждый мог быстро освоиться.
клиентская сторона отправляет данные на сервер посредством потоковой передачи
stream = ss.createStream();
blobstream=ss.createBlobReadStream(data);
blobstream.pipe(stream);
ss(socket).emit('data.stream',stream,{},function(err,successful_db_insert_id){
//if you get back the id it went into the db and everything worked
});
сервер получает поток со стороны клиента и затем отвечает, когда все готово
ss(socket).on('data.stream.out',function(stream,o,c){
buffer=[];
stream.on('data',function(chunk){buffer.push(chunk);});
stream.on('end',function(){
buffer=Buffer.concat(buffer);
db.insert(buffer,function(err,res){
res=insertedId[0];
c(null,res);
});
});
});
//Это вторая половина этой выборки данных и потоковой передачи на клиент
клиентская сторона запрашивает и получает потоковые данные с сервера
stream=ss.createStream();
binarystring='';
stream.on('data',function(chunk){
for(var I=0;i<chunk.length;i++){
binarystring+=String.fromCharCode(chunk[i]);
}
});
stream.on('end',function(){ data=window.btoa(binarystring); c(null,data); });
ss(socket).emit('data.stream.get,stream,o,c);
ответ на запрос потоковой передачи данных на стороне сервера
ss(socket).on('data.stream.get',function(stream,o,c){
stream.on('end',function(){
c(null,true);
});
db.find().stream().pipe(stream);
});
Самый последний - единственный, где я просто вытаскиваю его из задницы, потому что я еще не пробовал, но это должно сработать. На самом деле я делаю что-то подобное, но я записываю файл на жесткий диск, а затем использую fs.createReadStream для потоковой передачи его клиенту. Так что не уверен, если 100%, но из того, что я прочитал, должно быть, я вернусь к вам, как только я проверю это.
Ps, кто-нибудь хочет меня обидеть из-за моей разговорной манеры говорить, я канадец, и я люблю говорить "ах", подойди ко мне со своими объятиями и ударишь братан/сестренку: D