json - 如何在 sails-mongo 上进行非常大的查询?

标签 json node.js sails.js sails-mongo

我正在使用 sails 0.11.2。使用最新的 sails-mongo 适配器。 我有一个非常大的数据库(千兆字节的数据),主要包含时间戳和值。我使用蓝图 API 对其进行查询。

如果我使用 localhost:1337/datatable?limit=100000000000 进行查询,nodejs 将在 0.12 上挂起并占用大量 CPU,并在 v4 上崩溃。它在 toJSON 函数上崩溃。

我发现我需要在 API 上进行多个查询。但我不知道如何继续制作它。

如何进行多个查询“不会破坏”我的服务器?


更新:

在具有最新水线和 sails-mongo 的新版本 0.12.3 上,查询更加顺畅。云上的崩溃是因为我没有足够的 RAM 来处理同一个 T2.micro 实例上的 sailsjs 和 mongodb。

我已将 mongodb 服务器移至 M3.Medium 实例。现在服务器不再崩溃,但卡住了。我正在使用跳过限制,它对于 sails.js 效果很好,但对于 mongodb 来说是一种极大的资源浪费!

Mongodb使用limit=skip+limit进行内部查询。然后将光标移至所需数据处并返回。当您进行大量分页时,您正在使用大量内部查询。随着查询大小的增加。

最佳答案

this article解释说,避免 MongoDB 中资源浪费的方法是避免使用 skip并巧妙地利用_id作为您查询的一部分。

我没有使用 sails mongo,但我确实通过在 Nodejs 中使用 mongo 驱动程序实现了上述想法:

/**
 * Motivation:
 * Wanted to put together some code that used:
 *  - BlueBird (promises)
 *  - MongoDB NodeJS Driver
 *  - and paging that did not rely on skip()
 *
 * References:
 * Based on articles such as:
 * https://scalegrid.io/blog/fast-paging-with-mongodb/
 * and GitHub puclic code searches such as:
 * https://github.com/search?utf8=%E2%9C%93&q=bluebird+MongoClient+_id+find+limit+gt+language%3Ajavascript+&type=Code&ref=searchresults
 * which yielded smaple code hits such as:
 * https://github.com/HabitRPG/habitrpg/blob/28f2e9c356d7053884107d90d04e28dde75fa81b/migrations/api_v3/coupons.js#L71
 */

  var Promise = require('bluebird'); // jshint ignore:line
  var _ = require('lodash');
  var MongoClient = require('mongodb').MongoClient;
  var dbHandleForShutDowns;

  // option a: great for debugging
  var logger = require('tracer').console();
  // option b: general purpose use
  //var logger = console;

  //...

    var getPage = function getPage(db, collectionName, query, projection, pageSize, processPage) {
      //console.log('DEBUG', 'filter:', JSON.stringify(query,null,2));
      projection = (projection) ? projection['_id']=true : {'_id':true};
      return db
        .collection(collectionName)
        .find(query)
        .project(projection)
        .sort({'_id':1}).limit(pageSize)
        .toArray() // cursor methods return promises: http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#toArray
        .then(function processPagedResults(documents) {
          if (!documents || documents.length < 1) {
            // stop - no data left to traverse
            return Promise.resolve();
          }
          else {
            if (documents.length < pageSize) {
              // stop - last page
              return processPage(documents);
            }
            else {
              return processPage(documents) // process the results of the current page
                .then(function getNextPage(){ // then go get the next page
                  var last_id = documents[documents.length-1]['_id'];
                  query['_id'] = {'$gt' : last_id};
                  return getPage(db, collectionName, query, projection, pageSize, processPage);
                });
            }
          }
        });
    };

    //...

    return MongoClient
      .connect(params.dbUrl, {
        promiseLibrary: Promise
      })
      .then(function(db) {
        dbHandleForShutDowns = db;
        return getPage(db, collectionName, {}, {}, 5, function processPage(pagedDocs){console.log('do something with', pagedDocs);})
          .finally(db.close.bind(db));
      })
      .catch(function(err) {
        console.error("ERROR", err);
        dbHandleForShutDowns.close();
      });

以下两节展示了代码如何操作 _id并将其作为查询的一部分:

 .sort({'_id':1}).limit(pageSize)
 // [...]
var last_id = documents[documents.length-1]['_id'];
query['_id'] = {'$gt' : last_id};

总体代码流程:

  1. getPage()处理工作,可以设置pageSizequery根据您的喜好:

    return getPage(db, collectionName, {}, {}, 5, function processPage(pagedDocs){console.log('do something with', pagedDocs);})
    
  2. 方法签名:

    var getPage = function getPage(db, collectionName, query, projection, pageSize, processPage) {
    
  3. 进程 pagedResults一旦可用:

    return processPage(documents) // process the results of the current page
    
  4. 转到下一页:

    return getPage(db, collectionName, query, projection, pageSize, processPage);
    
  5. 当没有更多数据时,代码将停止:

    // stop - no data left to traverse
    return Promise.resolve();
    
  6. 或者在处理最后一页数据时会停止:

    // stop - last page
    return processPage(documents);
    

我希望这能提供一些启发,即使它不是满足您需求的精确解决方案。

关于json - 如何在 sails-mongo 上进行非常大的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33859850/

相关文章:

node.js 无需刷新即可获取新数据

node.js - 添加用于参数验证的快速中间件

node.js - Sails.js 中的唯一属性失败

javascript - 使用 sequelize ORM 连接到 node.js 上的 Amazon RDS Postgres 数据库时出现问题

javascript - Express js,将尾随 "/"添加到所有网址

mysql - Sails JS 和 mySQL 自定义 ID 名称不适用于蓝图

ios - 分组部分不显示在表格 View 中

java - 解析 JSON 数据时出错 - 异步任务

javascript - 如何使用递归解析json时获取id?

javascript - 将多个excel文件转换为json