MongoTemplateの公式ドキュメント:
1. 登録・削除・更新・検索操作
ネイティブMongoDB:
Queryオブジェクト
-
Queryオブジェクトを作成(すべての条件を格納する)、その後Criteriaオブジェクトを作成(条件を構築する)
-
精確な条件:criteria.and("key").is("値") フレーズ条件:criteria.and("key").regex("値")
-
条件をまとめる:query.addCriteria(criteria)
-
大きさ比較(新しいCriteriaを作成):Criteria gt = Criteria.where("key").gt("値") 小ささ比較(新しいCriteriaを作成):Criteria lt = Criteria.where("key").lt("値") 5. Query.addCriteria(new Criteria().andOperator(gt,lt));
-
1つのQueryには1つのandOperator()のみ使用可能。その引数はCriteria配列でも可。
-
ソート:query.with(new Sort(Sort.Direction.ASC, "age").and(new Sort(Sort.Direction.DESC, "date")))
2. MongoTemplateによるグループ化・ソート・複雑な操作
| **グループ化手法** | **理解の難しさ** | **パフォーマンス比較** | **推奨度** |
|---|---|---|---|
| mongoTemplate.group(); | 比較的シンプル | 70万件データで2分30秒 | SpringBoot環境では非推奨 |
| mongoTemplate.aggregation(); | 理解後は非常に便利 | 同じ環境で10秒未満 | 推奨 |
1、mongoTemplate.group(); グループ化可能だがソート不可、非推奨
// 絞り込み条件の設定
Criteria criteria = new Criteria();
criteria.andOperator(
// getMsgTimeがstartTimeより大きくendTimeより小さいデータを抽出
Criteria.where("getMsgTime").gte(startTime),
Criteria.where("getMsgTime").lte(endTime));
// MongoDBの"deviceCode"でグループ化、デフォルトでグループ化フィールドを保持
GroupBy groupBy = GroupBy.key("deviceCode")
// 追加のフィールドを初期化して保持
.initialDocument("{ count: 0 , onlineCount: 0 , lastTime: 0}")
// グループ化後のデータに対して計算を行う。docは現在の文書、prevは結果文書。func内ではJavaScript構文を使用可能
.reduceFunction("function(doc, prev) { prev.count++ ; if(doc.ctlStatus == 1){prev.onlineCount += 1 ;prev.lastTime = doc.getMsgTime ; }}");
// criteria:絞り込み条件、CTL_HEART_BEAT:コレクション名、DeviceGroupByResult.class:結果オブジェクト
GroupByResults<DeviceGroupByResult> results = mongoTemplate.group(criteria, "CTL_HEART_BEAT", groupBy, DeviceGroupByResult.class);
/** 結果を受け取るオブジェクトは、保持するフィールドをオブジェクトにまとめ、getter/setterを追加する
* DeviceGroupByResult.classにはdeviceCode、count、onlineCount、lastTimeなどのプロパティが含まれている。
*/
// 結果セットを処理する。iteratorオブジェクトのみ取得可能。リストのように扱うのは困難
Iterator<DeviceGroupByResult> iterator = results.iterator();
while (iterator.hasNext()) {
// ソースコードを見ると、result.iteratorは結果セットを返すが、イテレータでのみ読み取り可能
DeviceGroupByResult deviceGroupByResult = iterator.next();
}
2、mongoTemplate.aggregation(); グループ化とソート、推奨される方法
// 絞り込み条件の設定
Criteria criteria = new Criteria();
criteria.andOperator(
// getMsgTimeがstartTimeより大きくendTimeより小さいデータを抽出
Criteria.where("getMsgTime").gte(startTime),
Criteria.where("getMsgTime").lte(endTime));
// MongoDBのdevice_codeでグループ化
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(criteria),// 絞り込み条件を追加
Aggregation.group("deviceCode").first("deviceCode").as("deviceCode") // deviceCodeでグループ化し、フィールドを保持
.last("getMsgTime").as("lastTime")// 最終時間を保持
.count().as("count")// カウント
// ctlStatusは文字列としてMongoDBに保存されているため、合計を計算するにはListに格納する必要がある
.push("ctlStatus").as("currentCtlStatusList")
.push("getMsgTime").as("cuurentCtlGetTimeList")// なぜかgetMsgTimeもpushしているのは、ctlstatus==1のときの時刻を取得するため
// ソートはグループ化の後に指定するため、lastTimeのみ指定可能。グループ化前に指定する場合はgetMsgTimeなどのデータベースフィールドが必要
// sortは70万件のデータではパフォーマンスが悪く、エラーが発生する可能性がある
Aggregation.sort(Sort.by(Sort.Order.asc("lastTime")))
);
// aggregation:すべての条件を含む、CTL_HEART_BEAT:コレクション名、DeviceGroupByResult.class:結果オブジェクト
AggregationResults<DeviceGroupByResult> deviceGroupByResults = mongoTemplate.aggregate(aggregation, "CTL_HEART_BEAT", DeviceGroupByResult.class);
// この方法は非常に使いやすく
List<DeviceGroupByResult> list = deviceGroupByResults.getMappedResults();
3、ループによる検索(複数回の操作が必要な場合)
Criteria criteria = new Criteria();
// timeFrames:時間のリスト
for (String time : timeFrames) {
// aggregationに絞り込み条件を設定
Aggregation aggregation = Aggregation.newAggregation(
// 新しいCriteria条件を追加する必要があることに注意
// 通常のロジックでは外側のラッパーは不要だが、こうした場合
// 第1回目は問題なし、第2回目以降は複数回の絞り込みエラーが発生するため、暗黙的なパラメータ渡しを行う
Aggregation.match(new Criteria().andOperator(criteria.where("STATISTICS_YEAR").is(time), criteria)),
Aggregation.group("STATISTICS_TIME").first("STATISTICS_TIME").as("time").sum("CAR_FLOW").as("count"),
Aggregation.sort(Sort.by(Sort.Order.asc("time")))
);
AggregationResults<CarFlowResultVO> carFlowResultVOs = mongoTemplate.aggregate(aggregation, tableName, CarFlowResultVO.class);
carFlowResultVOList = carFlowResultVOs.getMappedResults();
carFlowResultVOMap.put(String.valueOf(count), carFlowResultVOList);
carFlowResultVOList = new ArrayList<>();
count++;
}
転載:https://www.cnblogs.com/tiankx/p/13957842.html