65.9K
CodeProject 正在变化。 阅读更多。
Home

一个类似于 MyBatis 风格的聚合和普通 MongoDB 查询框架

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2013 年 9 月 10 日

Apache

2分钟阅读

viewsIcon

13855

一个执行聚合和普通 MongoDB 查询的 MyBatis 风格框架

Mingo 框架概述

Mingo 简介

Mingo 是一个免费开源框架,用于执行聚合和纯 MongoDB 查询,使开发人员可以简单方便地创建查询过程。

为什么选择 Mingo?

通常,为了实现和使用新的 MongoDB 查询,开发人员必须:

  • 在 MongoDB 控制台中编写和验证查询。
  • 使用纯 Java 驱动程序或某些 ORM 框架(Spring Data、Morphia 等)在 Java 中实现查询。
  • 进行测试。

使用 Spring Mongo Data 实现的通用聚合查询如下所示:

  public Map<String, Integer> getCountByTags(ModerationStatus moderationStatus) {
      DBObject matchOperator = start().push(MATCH.getMongoName())
      .add("moderationStatus", moderationStatus != null ? moderationStatus.name() :
          ModerationStatus.STATUS_NOT_MODERATED.name()).get();
      DBObject unwindOperator = start().add(UNWIND.getMongoName(), "$tags").get();
      DBObject projectOperator = start().push(PROJECT.getMongoName()).
      add("moderationStatus", 1).add("tags", 1)
          .push("count").add("$add", new Integer[]{1}).pop().pop().get();
      DBObject groupOperator = start().push(GROUP.getMongoName()).
      add("_id", "$tags").push("totalCount")
          .add(SUM.getMongoName(), "$count").pop().pop().get();
      List<DBObject> operators = Lists.newArrayList
      (matchOperator, unwindOperator, projectOperator, groupOperator);
      Map<String, Integer> result = reviewConverter.convertCountByTags(
          getAsBasicDBList(aggregate("review", operators)));
      return result;
  }

这段代码很难阅读和维护(我们的团队并不反对 Spring Mongo Data,我们只是陈述一个事实,即以流畅风格实现的大型查询很难阅读和支持)。每次开发人员想要更改查询时,他都应该在 MongoDB 控制台中编写和验证查询,然后在代码中实现这些更改。通常(尤其是在大型查询的情况下),此操作需要太多时间。当然,您可以直接更改代码,但它不如在控制台中那样容易、快速和清晰。在找到可接受的查询变体之前,您必须更改和编译代码、运行测试多少次?或者更快的方法是在 mongo 控制台中进行操作并将其按原样保存在 XML 文件中以保持代码的整洁?让我们看看使用 Mingo 实现的相同查询是什么样的

public Map<String, Integer> getCountByTags(ModerationStatus moderationStatus) {
 Map<String, Object> parameters = Maps.newHashMap();
 parameters.put("moderationStatus", moderationStatus);        
 return mingoTemplate.queryForObject("mingotest.review.getCountByTags", Map.class, parameters);
}   

感受一下差异。 12 行代码,还是 3 行?我们认为答案很明显。

我们从代码中删除了查询创建逻辑到 XML 文件中

  <query id="getCountByTags" type="aggregation">
      {$match :  {"moderationStatus": "#moderationStatus"}},
      {$unwind:  "$tags"},
      {$project: {moderationStatus:1, tags: 1, count: {$add: [1]}}},
      {$group:   {_id: "$tags", totalCount: {$sum: "$count"}}}  
  </query>   

Mingo 解决了以下问题:

  • 开发周期长
  • 查询创建逻辑使代码混乱
  • 无法在运行时基于查询参数选择不同的查询
  • 每次在添加到查询条件/验证参数之前,都要对每个参数进行null检查

该项目代码存在并且可以在 github 上克隆。

此外,您可以在项目 Wiki 中阅读更多内容。

现在 Mingo 不支持 insertupdate 操作,因为最初计划将其作为对某些 ORM 框架(Spring Data、Morphia 等)的补充,这些框架已经在此项目中使用。但我们将在未来改变这种情况:在下一个版本中添加 insertupdate 操作(将在项目 Wiki 中描述下一个版本中将添加的所有功能列表)。

我正在积极寻找可以合作继续更新 Mingo 框架等的开发人员。我很高兴听到您的想法和建议,这对我非常重要。 Mingo 是一个年轻且快速发展的框架,我认为我们可以一起使它更好、更安全、更快。请随时在评论中写下您的问题或直接发送电子邮件至:mingoframework@gmail.com

感谢您的关注。

© . All rights reserved.