java - 以 google.gson.JsonArray 格式从 MongoDB 返回大型数据集的有效方法

标签 java json mongodb performance gson

我有一个 mongo DB 查询,它返回 10000 多条记录。我想以 GSON (google JSON) 格式返回业务服务。以下是代码片段。

        String mongoClientURI = null;
        mongoClientURI = "mongodb://" + dbUser + ":" + pwd + "@" + host + ":" + port + "/" + databaseName;


        MongoClient client = new MongoClient(new MongoClientURI(mongoClientURI));
        MongoDatabase db = client.getDatabase(databaseName);

        // Find query returns more than 10K records
        FindIterable<Document> dbResult = db.getCollection("mycollection").find();  

        // This line takes too much time & CPU      
        List<Document> result = getDocumentArray(dbResult);

        // This line takes too much time & CPU
        JsonArray finalResult = getJSONArray(result);

    public static List<Document> getDocumentArray(FindIterable<Document> input) {
        List<Document> output = new ArrayList<Document>();
        for (Document doc : input) {
            output.add(doc);
        }
        return output;
    }

    public static JsonArray getJSONArray(Iterable<Document> docs) {
        JsonArray result = new JsonArray();
        if (docs == null) {
            return result;
        }

        for (Document doc : docs) {
            JsonObject jsonObject;
            JsonParser parser = new JsonParser();
            try {
                jsonObject = parser.parse(doc.toJson()).getAsJsonObject();
                result.add(jsonObject);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        return result;
    }

问题是在从 MongoDB 获取数据并将其转换为 GSON 数组时需要花费大量时间和 CPU 周期。谁能告诉我从 mongodb 获取大数据集到 gson 格式的有效方法是什么?

通常我会得到大约 10k 到 20K 条记录(最多 50K)。我需要把它们全部归还。我的 UI 组件需要一次性渲染所有记录来呈现数据。一般来说,人们使用带有分页的数据网格,因此它一次不会有太多记录,但在我的例子中,我有 map 组件,它获取所有记录并动态创建一组对象。

任何帮助将不胜感激。

阿图尔苏雷卡

最佳答案

有效的方法是不要一次性返回所有文档,而是使用 skip()limit() 函数来实现分页。如果您的集合有一百万个文档,那么您最终会在内存中得到一个很大的List,您甚至可能不需要一次性在 UI 上显示所有文档。

以下是实现分页的方法:

1st Call : db.getCollection("mycollection").find().limit(10);
2nd Call : db.getCollection("mycollection").find().skip(10).limit(10);
3rd Call : db.getCollection("mycollection").find().skip(20).limit(10);

skip 驱动页码,而 limit 驱动每页的项目。您也可以使用 sort 来定义排序(here's 文档)。

另一种方法是使用排队机制或流式传输来滚动光标中的所有文档并将其推送到队列/客户端。

更新

您可以采取以下措施来加快现有实现的速度:

  • Iterable 转换为 parallelStream 以更快地处理文档(查看 this SO 答案如何将 Iterable 转换为 )
  • 不要为每个文档创建 JsonParser 实例。创建一个实例一次并将其用于所有文档。
  • 增加应用程序的 Xmx

关于java - 以 google.gson.JsonArray 格式从 MongoDB 返回大型数据集的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44645925/

相关文章:

java - 在 Camera2 api 上使用 captureBurst 时 JPEG 回调超时

ruby - 使用 Ruby 驱动程序的 MongoDB 组

javascript - module.require(...).* 是否返回 module.exports.* 的副本或它的引用?

java - 一个接口(interface)多种实现。如何在运行时获得正确的

java - 如何通过 XPages Java Bean 上传和保存附件

javascript - 在 jQuery 中制作 JSON 对象的最佳方法是什么?

python - 从DDFS读取数据ValueError : No JSON object could be decoded

javascript - 用户数据未使用 Node API 插入 mongodb

java - 我怎么知道 Object 是否是 String 类型的对象?

json - 由于 json 指针,Sphinx 无法包含我的 JSON 定义文件