Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/437.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.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
Javascript NodeJS、MongoDB、Mongoose无阻塞保存大数据_Javascript_Node.js_Mongodb_Express_Mongoose - Fatal编程技术网

Javascript NodeJS、MongoDB、Mongoose无阻塞保存大数据

Javascript NodeJS、MongoDB、Mongoose无阻塞保存大数据,javascript,node.js,mongodb,express,mongoose,Javascript,Node.js,Mongodb,Express,Mongoose,我目前正在使用NodeJS、ExpressJS和EJS、MongoDB和Mongoose开发一个简单的应用程序。下面是我面临的问题的简要介绍,并寻求一些建议 情景 1在特定事件中,调用使用SOAP的web服务并提取数据 2 API一次返回大约一百万行数据 3使用mongoose将拉取的数据保存到MongoDB中 代码 数据库模型-myModel.js 拉取连接到控制器的数据-app.js 需要问题/建议 我面临的问题是,在将所有数据保存到数据库之前,服务器会被阻止,并且不会执行其他功能,如为并发

我目前正在使用NodeJS、ExpressJS和EJS、MongoDB和Mongoose开发一个简单的应用程序。下面是我面临的问题的简要介绍,并寻求一些建议

情景

1在特定事件中,调用使用SOAP的web服务并提取数据

2 API一次返回大约一百万行数据

3使用mongoose将拉取的数据保存到MongoDB中

代码

数据库模型-myModel.js

拉取连接到控制器的数据-app.js

需要问题/建议

我面临的问题是,在将所有数据保存到数据库之前,服务器会被阻止,并且不会执行其他功能,如为并发用户呈现页面或保存更多数据

我正在创建一个视图,该视图也将返回保存的数据。这些同样是数百万行的数据——但这次从MongoDB获取并传递到EJS中的视图


如果您能提供任何帮助/建议,以优化运行并行进程和计算大量数据的性能,我们将不胜感激。

听起来像是数据复制问题,因为您的数据没有在多个节点上复制。我建议检查您的MongoDB是如何设置的。复制将提高您的服务的可用性,一个节点响应初始请求,而其他节点则可以自由地使用相同数据的副本来响应新的读/写操作

如果所有读取都是百万行读取,则可能需要几个节点

谷歌很快就推出了这个关于复制的MongoDB教程。开头一段指出复制提供了冗余并提高了数据可用性


听起来像是数据复制问题,因为您的数据没有在多个节点上复制。我建议检查您的MongoDB是如何设置的。复制将提高您的服务的可用性,一个节点响应初始请求,而其他节点则可以自由地使用相同数据的副本来响应新的读/写操作

如果所有读取都是百万行读取,则可能需要几个节点

谷歌很快就推出了这个关于复制的MongoDB教程。开头一段指出复制提供了冗余并提高了数据可用性


您可能想学习如何使用

创建一个可写流,当使用某些数据调用mongodb的_write时,该流将在mongodb中插入数据。最好是缓冲数据并以小批量插入

创建一个转换流,在xml块到达json对象时对其进行解析。如果您可以在上获得一个现成的流解析器,那么您将是幸运的

以一百万个项目的形式获取SOAP响应流,但仍然是一个响应流和管道:SOAP响应->转换->写入。这可能需要一些工作

侦听最后一个流的完成和所有流的错误,当第一次发出完成或错误时,操作结束。拆下管道设置。拆下管道

此外,流可以暂停和恢复,因此您可能希望使用它来保持数据流处于受控状态


上述方法并没有提高服务器的处理速度,只是有助于保持其响应速度。如果您想真正扩大规模,请构建一个专门的xml-to-db流媒体服务集群。

您可能想学习如何使用

创建一个可写流,当使用某些数据调用mongodb的_write时,该流将在mongodb中插入数据。最好是缓冲数据并以小批量插入

创建一个转换流,在xml块到达json对象时对其进行解析。如果您可以在上获得一个现成的流解析器,那么您将是幸运的

以一百万个项目的形式获取SOAP响应流,但仍然是一个响应流和管道:SOAP响应->转换->写入。这可能需要一些工作

侦听最后一个流的完成和所有流的错误,当第一次发出完成或错误时,操作结束。拆下管道设置。拆下管道

此外,流可以暂停和恢复,因此您可能希望使用它来保持数据流处于受控状态


上述方法并没有提高服务器的处理速度,只是有助于保持其响应速度。如果您想真正扩大规模,请构建一个专用xml-to-db流媒体服务集群。

您的存储不是异步的。这条线路阻塞了:

saveData.save();
相反,异步保存模型,并在保存完成后传递要运行的函数:

function getProducts(req, res){
    var post = req.body;
    var url = 'http://www.example.com/?wsdl';
    soap.createClient(url, function(err, client) {
        client.setSecurity(new soap.BasicAuthSecurity(User, Pass));
        client.someMethod(function(err, result) {
            var product = result.DATA.item;
            for(var i=0; i<product.length; i++) {
                var saveData = new Product({
                    rowIndex: product.ROW_INDEX,
                    prodId: product.PROD_ID,
                    prodDesc: product.PROD_DESC,
                    prodCategory: product.PROD_CATEGORY,
                });
                saveData.save( function (err, data) {
                    // any statements here will run when this row is saved,
                    // but the loop will continue onto the next product without
                    // waiting for the save to finish
                });
            }           
        });
    });   
    res.send("Getting the data! You can browse the site while you wait...");
}

这样,整个循环将几乎立即运行,数据将在输入时保存。同时,您的节点进程可以自由地处理其他web请求。

您的保存不是异步的。这条线路阻塞了:

saveData.save();
相反,异步保存模型,并在保存完成后传递要运行的函数:

function getProducts(req, res){
    var post = req.body;
    var url = 'http://www.example.com/?wsdl';
    soap.createClient(url, function(err, client) {
        client.setSecurity(new soap.BasicAuthSecurity(User, Pass));
        client.someMethod(function(err, result) {
            var product = result.DATA.item;
            for(var i=0; i<product.length; i++) {
                var saveData = new Product({
                    rowIndex: product.ROW_INDEX,
                    prodId: product.PROD_ID,
                    prodDesc: product.PROD_DESC,
                    prodCategory: product.PROD_CATEGORY,
                });
                saveData.save( function (err, data) {
                    // any statements here will run when this row is saved,
                    // but the loop will continue onto the next product without
                    // waiting for the save to finish
                });
            }           
        });
    });   
    res.send("Getting the data! You can browse the site while you wait...");
}
这样,整个循环将几乎立即运行,数据将在输入时保存。同时,您的节点进程可以自由地服务于其他web请求<
/p> 尝试使用将您保存到数据库的时间限制为一次最多N个文档。尝试使用将您保存到数据库的时间限制为一次最多N个文档。如果要求不高,请您根据示例代码详细说明post函数的示例?非常感谢!我使用示例代码添加了一个示例。基本上,通过将save方法传递给一个函数,它不再阻塞。如果它没有要求太多,那么您可以根据示例代码用一个详细的post函数示例向我解释一下吗?非常感谢!我使用示例代码添加了一个示例。基本上,通过向save方法传递一个函数,它不再阻塞。
function getProducts(req, res){
    var post = req.body;
    var url = 'http://www.example.com/?wsdl';
    soap.createClient(url, function(err, client) {
        client.setSecurity(new soap.BasicAuthSecurity(User, Pass));
        client.someMethod(function(err, result) {
            var product = result.DATA.item;
            for(var i=0; i<product.length; i++) {
                var saveData = new Product({
                    rowIndex: product.ROW_INDEX,
                    prodId: product.PROD_ID,
                    prodDesc: product.PROD_DESC,
                    prodCategory: product.PROD_CATEGORY,
                });
                saveData.save( function (err, data) {
                    // any statements here will run when this row is saved,
                    // but the loop will continue onto the next product without
                    // waiting for the save to finish
                });
            }           
        });
    });   
    res.send("Getting the data! You can browse the site while you wait...");
}