Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 将mongoose流转换为数组_Node.js_Mongodb_Stream_Mongoose - Fatal编程技术网

Node.js 将mongoose流转换为数组

Node.js 将mongoose流转换为数组,node.js,mongodb,stream,mongoose,Node.js,Mongodb,Stream,Mongoose,我曾与mongodb合作过,但对mongoose ORM来说是个新手。我试图从一个集合中获取数据,explain()输出显示为50ms。通过mongoose获取数据的总时间为9秒。以下是查询: Node.find({'dataset': datasetRef}, function (err, nodes){ // handle error and data here }); 然后我在我查询的字段上应用了索引。explain()输出现在显示为4ms。但通过mongoose检索数据的总时间没

我曾与mongodb合作过,但对mongoose ORM来说是个新手。我试图从一个集合中获取数据,explain()输出显示为50ms。通过mongoose获取数据的总时间为9秒。以下是查询:

Node.find({'dataset': datasetRef}, function (err, nodes){
   // handle error and data here
});
然后我在我查询的字段上应用了索引。explain()输出现在显示为4ms。但通过mongoose检索数据的总时间没有改变。然后我搜索了一下,发现使用lean()有助于使mongoose中读取查询的性能非常接近本机mongodb

因此,我将查询更改为:

Node.find({'dataset': datasetRef})
.lean()
.stream({transform: JSON.stringify})
.pipe(res)
这完全解决了性能问题。但最终的结果是JSON文档流如下所示:

{var11: val11, var12: val12}{var21: val21, var22: val22} ...
我如何解析它以形成一个文档数组?或者我根本不应该使用流?在我看来,如果我计划在后端形成数组,那么使用流是没有意义的,因为我将不得不等待所有文档被读入内存。但我也认为,在前端解析和创建整个数组可能代价高昂

在这种情况下,如何在不阻塞网络的情况下实现最佳性能

更新

我正在尝试使用直通流解决这个问题。但是,我还不能在JSON对象之间插入逗号。请参阅下面的代码:

res.write("[");

var through = require('through');
var tr = through(
  function write(data){
    this.queue(data.replace(/\}\{/g,"},{"));
  }
);

var dbStream = db.node.find({'dataset': dataSetRef})
.lean()
.stream({'transform': JSON.stringify});

dbStream.on("end", function(){
    res.write("]");
});

dbStream
.pipe(tr)
.pipe(res);
有了这个,我可以得到开头的“[”和结尾的“]”。然而,仍然无法将patten“}{”替换为“},{”。不确定我做错了什么

更新2

现在明白了替换不起作用的原因了。由于我将转换函数指定为JSON.stringify,它一次读取一个JSON对象,因此不会遇到模式
}{
,因为它不会一次拾取多个JSON元素

现在我修改了我的代码,并编写了一个自定义转换函数,该函数执行JSON.stringify,然后在末尾附加一个逗号。我在这里面临的唯一问题是,我不知道它何时是流中的最后一个JSON对象。因为我不想在这种情况下附加逗号。现在,我在结束时附加一个空JSON对象但不知何故,这似乎不是一个令人信服的想法。以下是代码:

res.write("[");
function transform(data){
    return JSON.stringify(data) + ",";
}

var dbStream = db.node.find({'dataset': dataSetRef})
.lean()
.stream({'transform': transform});

dbStream.on("end", function(){
    res.write("{}]");
});

dbStream
.pipe(res);
我在这里面临的唯一问题是,我不知道它何时是流中的最后一个JSON对象

但是您知道哪一个是第一个。知道了这一点,您可以在每个对象(第一个对象除外)前面加逗号,而不必加逗号。为此,请在闭包中设置转换函数:

function transformFn(){

    var first = true;

    return function(data) {

        if (first) {

            first = false;
            return JSON.stringify(data);
        }
        return "," + JSON.stringify(data);
    }
}
现在,您可以调用该函数并将其设置为实际转换

var transform = transformFn();
res.write("[");
var dbStream = db.node.find({'dataset': dataSetRef})
.lean()
.stream({'transform': transform});

dbStream.on("end", function(){
    res.write("]");
});

dbStream
.pipe(res);

我喜欢@cdbajorin的解决方案,因此我创建了一个更具可读性的版本(ES6):


@cbajorin和@rckd都给出了正确的答案

然而,一直重复这段代码似乎很痛苦

因此,我的解决方案使用一个额外的转换流来实现同样的效果

    import { Transform } from 'stream'

class ArrayTransform extends Transform {
    constructor(options) {
        super(options)
        this._index = 0
    }

    _transform(data, encoding, done) {
        if (!(this._index++)) {
            // first element, add opening bracket
            this.push('[')
        } else {
            // following element, prepend comma
            this.push(',')
        }
        this.push(data)
        done()
    }

    _flush(done) {
        if (!(this._index++)) {
            // empty
            this.push('[]')
        } else {
            // append closing bracket
            this.push(']')
        }
        done()
    }
}
这反过来又可以用作:

const toArray = new ArrayTransform();
Model.find(query).lean().stream({transform: JSON.stringify })
    .pipe(toArray)
    .pipe(res)

编辑:添加了空检查

是否尝试在第一个查询中传递精益选项?Node.find({'dataset':datasetRef}).lean().exec(函数(err,nodes){…});是的。问题是,文档之前作为单个数组存储在文档中,并存储在gridfs中。因此,在请求文档之前,响应在几毫秒内开始流式传输。现在,如果我要从该模型移动到该规范化模型,消除gridfs,我需要使用流式传输,否则响应会从后端延迟。这是什么原因如何使用直通流将模式(如
}{
)替换为
},{
)呢?我正在尝试,但无法做到这一点
    var mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/shoppingdb');
    var Sports = mongoose.model('sports', {});

    var result = [];
    var prefix_out = "your info";

      Sports.find({"goods_category": "parts"}).
      cursor().
      on("data", function(doc){
        //stream ---> string
          var str = JSON.stringify(doc)
        //sring ---> JSON
          var json = JSON.parse(str);
        //handle Your Property
          json.handleYourProperty = prefix_out + json.imageURL;              
          result.push(result);
      }).
      on('error', function(err){
          console.log(err);
      }).
      on('close', function(){
          console.log(result);
      });
    var mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/shoppingdb');
    var Sports = mongoose.model('sports', {});

    var result = [];
    var prefix_out = "your info";

      Sports.find({"goods_category": "parts"}).
      cursor().
      on("data", function(doc){
        //stream ---> string
          var str = JSON.stringify(doc)
        //sring ---> JSON
          var json = JSON.parse(str);
        //handle Your Property
          json.handleYourProperty = prefix_out + json.imageURL;              
          result.push(result);
      }).
      on('error', function(err){
          console.log(err);
      }).
      on('close', function(){
          console.log(result);
      });