private void doReduce(List<Tuple2<String, Integer>> collect) {
    logger.debug("come into doReduce -->");
    Map<String, Document> cacheMap = new HashMap<String, Document>();
    for (Tuple2<String, Integer> tuple : collect) {
      if (!tuple._1().startsWith("VersionDetail")) {
        continue;
      }
      // 缓存汇总结果
      doCacheEventDetailInfo(cacheMap, tuple);
    }
    Set<String> keys = cacheMap.keySet();
    for (String keyStr : keys) {
      String key[] = keyStr.split(":");
      String tableName = key[0];
      Document versionDetailDoc = cacheMap.get(keyStr);

      // 保存汇总结果到mongoDb
      versionDetailDao.saveOrUpdate(tableName, versionDetailDoc);
    }
  }
  /**
   * 缓存每条汇总结果
   *
   * @param cacheMap
   * @param tuple
   */
  private void doCacheEventDetailInfo(
      Map<String, Document> cacheMap, Tuple2<String, Integer> tuple) {
    logger.debug("come into doCacheEventDetailInfo ==> " + tuple._1() + " <--> " + tuple._2());
    // 解析表名:字段名1、字段名2:字段名1值:timeValue:appId:appVersion(tenantId)
    String keys[] = tuple._1().split(":");
    String tableName = keys[0];
    String fieldName1 = keys[1];
    String fieldName2 = keys[2];
    String fieldName1Value = keys[3];
    String timeValue = keys[4];
    String appId = keys[5];
    String appVersion = keys[6];
    String tenantId =
        (keys.length == 8 && keys[7] != null && !keys[7].trim().isEmpty()) ? (keys[7]) : "";
    String tenantIdKey =
        (keys.length == 8 && keys[7] != null && !keys[7].trim().isEmpty())
            ? (":" + keys[7])
            : ""; // 存在tenantId就加到keyStr中去

    Document versionDetailDoc = null;

    String newUserFromChannal = null;
    String updateUserFromChannal = null;
    String updateUserFromVersion = null;
    if ("newUserFromChannal".equals(fieldName1)) {
      newUserFromChannal = fieldName1Value;
    }
    if ("updateUserFromChannal".equals(fieldName1)) {
      updateUserFromChannal = fieldName1Value;
    }
    if ("updateUserFromVersion".equals(fieldName1)) {
      updateUserFromVersion = fieldName1Value;
    }
    String keyStr =
        tableName
            + ":"
            + timeValue
            + ":"
            + appId
            + ":"
            + appVersion
            + ":"
            + fieldName1
            + ":"
            + fieldName1Value
            + tenantIdKey;
    // 如果缓存命中,使用缓存的对象
    if (cacheMap.containsKey(keyStr)) {
      versionDetailDoc = cacheMap.get(keyStr);
    } else {
      versionDetailDoc =
          versionDetailDao.findOneBy(
              tableName,
              timeValue,
              appId,
              appVersion,
              newUserFromChannal,
              updateUserFromChannal,
              updateUserFromVersion,
              tenantId);
    }

    if (versionDetailDoc == null) {
      VersionDetail versionDetail = new VersionDetail();
      versionDetail.setAppId(appId);
      versionDetail.setAppVersion(appVersion);
      versionDetail.setTimeValue(timeValue);
      if (tenantId != null && !tenantId.trim().isEmpty()) {
        versionDetail.setTenantId(tenantId);
      }
      Gson gson = new Gson();
      versionDetailDoc = Document.parse(gson.toJson(versionDetail));
      ObjectId objId = new ObjectId();
      versionDetailDoc.put("_id", objId);
      versionDetailDoc.put(fieldName1, fieldName1Value);
    }
    if (versionDetailDoc.get(fieldName2) == null) {
      versionDetailDoc.put(fieldName2, tuple._2());
    } else {
      long fieldValue = 0;
      try {
        fieldValue = versionDetailDoc.getLong(fieldName2);
      } catch (ClassCastException e) {
        fieldValue = (long) versionDetailDoc.getInteger(fieldName2);
      }

      versionDetailDoc.put(fieldName2, (long) (fieldValue + tuple._2()));
    }
    cacheMap.put(keyStr, versionDetailDoc);
    return;
  }