mongodb 인덱스 지정

잔존율 조회
This commit is contained in:
2025-07-16 15:56:29 +09:00
parent e4b2b47a02
commit d439481822
12 changed files with 321 additions and 55 deletions

View File

@@ -0,0 +1,178 @@
package com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class IndicatorsRetentionLoadService extends IndicatorsLogLoadServiceBase {
public IndicatorsRetentionLoadService(
@Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate
) {
super(mongoTemplate);
}
@Override
public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("userCreate")
.localField("userGuid")
.foreignField("userGuid")
.as("userInfo");
UnwindOperation unwindOperation = Aggregation.unwind("userInfo");
Criteria criteria = makeCriteria(startTime, endTime, "userInfo.logDay");
AddFieldsOperation addFieldsOp = Aggregation.addFields()
.addField("createDate")
.withValue(DateOperators.dateFromString("$userInfo.logDay"))
.addField("loginDate")
.withValue(DateOperators.dateFromString("$logDay"))
.build();
AggregationOperation addFieldsOp2 = context -> new Document("$addFields",
new Document("daysSinceCreate",
new Document("$dateDiff", new Document()
.append("startDate", "$createDate")
.append("endDate", "$loginDate")
.append("unit", "day")
)
)
);
MatchOperation matchOp = Aggregation.match(
Criteria.where("daysSinceCreate").gte(1).lte(30)
);
AggregationOperation groupOp = context -> new Document("$group",
new Document("_id", new Document("cohortDate", "$userInfo.logDay")
.append("userGuid", "$userGuid"))
.append("loginDays", new Document("$addToSet", "$daysSinceCreate"))
);
AggregationOperation groupOp2 = context -> new Document("$group",
new Document("_id", "$_id.cohortDate")
.append("totalUsers", new Document("$sum", 1))
.append("d1_retained", new Document("$sum",
new Document("$cond", List.of(
new Document("$in", List.of(1, "$loginDays")),
1,
0
))
))
.append("d7_retention_users", new Document("$sum",
new Document("$cond", List.of(
new Document("$gt", List.of(
new Document("$size", new Document("$filter", new Document()
.append("input", "$loginDays")
.append("cond", new Document("$and", List.of(
new Document("$gte", List.of("$$this", 1)),
new Document("$lte", List.of("$$this", 7)))
))
)),
0
)),
1,
0
))
))
.append("d30_retention_users", new Document("$sum",
new Document("$cond", List.of(
new Document("$gt", List.of(
new Document("$size", new Document("$filter", new Document()
.append("input", "$loginDays")
.append("cond", new Document("$and", List.of(
new Document("$gte", List.of("$$this", 1)),
new Document("$lte", List.of("$$this", 30)))
))
)),
0
)),
1,
0
))
))
);
AggregationOperation lookupOp = context -> new Document("$lookup",
new Document("from", "userCreate")
.append("let", new Document("cohortDate", "$_id"))
.append("pipeline", List.of(
new Document("$match", new Document("$expr",
new Document("$eq", List.of("$logDay", "$$cohortDate"))
)),
new Document("$count", "totalCreated")
))
.append("as", "cohortInfo")
);
UnwindOperation unwindOp = Aggregation.unwind("cohortInfo", true);
AggregationOperation projectOp = context -> new Document("$project", new Document()
.append("_id", 0)
.append("logDay", "$_id")
.append("totalCreate", new Document("$ifNull", List.of("$cohortInfo.totalCreated", 0)))
.append("totalActiveUsers", "$totalUsers")
.append("d1_users", 1)
.append("d7_users", 1)
.append("d30_users", 1)
.append("d1_rate", new Document("$cond", List.of(
new Document("$gt", List.of("$cohortInfo.totalCreated", 0)),
new Document("$multiply", List.of(
new Document("$divide", List.of("$d1_retained", "$cohortInfo.totalCreated")),
100
)),
0
)))
.append("d7_rate", new Document("$cond", List.of(
new Document("$gt", List.of("$cohortInfo.totalCreated", 0)),
new Document("$multiply", List.of(
new Document("$divide", List.of("$d7_retention_users", "$cohortInfo.totalCreated")),
100
)),
0
)))
.append("d30_rate", new Document("$cond", List.of(
new Document("$gt", List.of("$cohortInfo.totalCreated", 0)),
new Document("$multiply", List.of(
new Document("$divide", List.of("$d30_retention_users", "$cohortInfo.totalCreated")),
100
)),
0
)))
);
List<AggregationOperation> operations = List.of(
lookupOperation,
unwindOperation,
Aggregation.match(criteria),
addFieldsOp,
addFieldsOp2,
matchOp,
groupOp,
groupOp2,
lookupOp,
unwindOp,
projectOp,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_LOGIN
, clazz
).getMappedResults();
}
}

View File

@@ -22,7 +22,7 @@ public abstract class IndicatorsLogLoadServiceBase implements IndicatorsLogLoadS
return new Criteria()
.andOperator(
Criteria.where(dateFieldName).gte(startDate),
Criteria.where(dateFieldName).lt(endDate)
Criteria.where(dateFieldName).lte(endDate)
);
}

View File

@@ -2,15 +2,23 @@ package com.caliverse.admin.Indicators.entity;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
@Getter
@Setter
@Document(collection = "currency")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}")
})
public class CurrencyItemLogInfo extends LogInfoBase{
private String id;
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private String tranId;

View File

@@ -3,6 +3,9 @@ package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.logs.Indicatordomain.CurrencyMongoLog;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@@ -11,9 +14,14 @@ import java.util.Map;
@Getter
@Setter
@Document(collection = "currency")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}")
})
public class CurrencyLogInfo extends LogInfoBase{
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private Double sapphireAcquired;

View File

@@ -3,6 +3,9 @@ package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.logs.Indicatordomain.ItemMongoLog;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@@ -10,9 +13,14 @@ import java.util.List;
@Getter
@Setter
@Document(collection = "item")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}")
})
public class ItemLogInfo extends LogInfoBase{
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private Integer totalItems;

View File

@@ -0,0 +1,42 @@
package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class RetentionInfo implements IndicatorsLog {
private String logDay;
private Integer totalCreate;
private Integer totalActiveUsers;
private Integer d1_users;
private Integer d7_users;
private Integer d30_users;
private Integer d1_rate;
private Integer d7_rate;
private Integer d30_rate;
public RetentionInfo(String logDay,
Integer totalCreate,
Integer totalActiveUsers,
Integer d1_users,
Integer d7_users,
Integer d30_users,
Integer d1_rate,
Integer d7_rate,
Integer d30_rate
) {
this.logDay = logDay;
this.totalCreate = totalCreate;
this.totalActiveUsers = totalActiveUsers;
this.d1_users = d1_users;
this.d7_users = d7_users;
this.d30_users = d30_users;
this.d1_rate = d1_rate;
this.d7_rate = d7_rate;
this.d30_rate = d30_rate;
}
}

View File

@@ -2,14 +2,22 @@ package com.caliverse.admin.Indicators.entity;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
@Getter
@Setter
@Document(collection = "userCreate")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}")
})
public class UserCreateLogInfo extends LogInfoBase{
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private String createdTime;

View File

@@ -2,6 +2,9 @@ package com.caliverse.admin.Indicators.entity;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@@ -10,9 +13,15 @@ import java.util.Map;
@Getter
@Setter
@Document(collection = "userLogin")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}")
})
public class UserLoginLogInfo extends LogInfoBase{
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private List<Map<String, Object>> sessions;

View File

@@ -121,9 +121,11 @@ public class IndicatorsResponse {
@Data
@Builder
public static class Retention{
private LocalDate date;
@JsonProperty("d-day")
private List<Dday> dDay;
private String logDay;
private Integer totalCreated;
private Integer d1_rate;
private Integer d7_rate;
private Integer d30_rate;
}
@Data
@Builder

View File

@@ -8,6 +8,8 @@ import java.util.stream.Collectors;
import com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice.*;
import com.caliverse.admin.Indicators.entity.*;
import com.caliverse.admin.domain.response.LogResponse;
import com.caliverse.admin.global.common.utils.DateUtils;
import com.caliverse.admin.logs.logservice.indicators.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -46,6 +48,7 @@ public class IndicatorsService {
private final IndicatorsWauLoadService indicatorsWauLoadService;
private final IndicatorsUgqCreateLoadService indicatorsUgqCreateLoadService;
private final IndicatorsMetaverServerLoadService indicatorsMetaverServerLoadService;
private final IndicatorsRetentionLoadService indicatorsRetentionLoadService;
private final IndicatorsDauService dauService;
private final IndicatorsNruService indicatorsNruService;
@@ -167,27 +170,25 @@ public class IndicatorsService {
}
// 유저 지표 Retention
public IndicatorsResponse retentionList(Map<String, String> requestParams){
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
LocalDateTime endDt = DateUtils.stringISOToLocalDateTime(requestParams.get("end_dt"));
List<RetentionInfo> retentionLogList = indicatorsRetentionLoadService.getIndicatorsLogData(
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
RetentionInfo.class);
List<IndicatorsResponse.Retention> retentionList = new ArrayList<>();
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
int cnt = dateRange.size();
for (LocalDate date : dateRange) {
List<IndicatorsResponse.Dday> dDayList = new ArrayList<>();
for (int i = 0; i < cnt; i++){
IndicatorsResponse.Dday dDay = IndicatorsResponse.Dday.builder()
.date("D+" + i)
.dif("0%")
.build();
dDayList.add(dDay);
}
cnt -- ;
IndicatorsResponse.Retention retention = IndicatorsResponse.Retention.builder()
.date(date)
.dDay(dDayList)
for (RetentionInfo info : retentionLogList){
IndicatorsResponse.Retention build = IndicatorsResponse.Retention.builder()
.logDay(info.getLogDay())
.totalCreated(info.getTotalCreate())
.d1_rate(info.getD1_rate())
.d7_rate(info.getD7_rate())
.d30_rate(info.getD30_rate())
.build();
retentionList.add(retention);
retentionList.add(build);
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.retentionList(retentionList)
@@ -202,29 +203,29 @@ public class IndicatorsService {
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
int cnt = dateRange.size();
for (LocalDate date : dateRange) {
List<IndicatorsResponse.Dday> dDayList = new ArrayList<>();
for (int i = 0; i < cnt; i++){
IndicatorsResponse.Dday dDay = IndicatorsResponse.Dday.builder()
.date("D+" + i)
.dif("0%")
.build();
dDayList.add(dDay);
}
cnt -- ;
IndicatorsResponse.Retention retention = IndicatorsResponse.Retention.builder()
.date(date)
.dDay(dDayList)
.build();
retentionList.add(retention);
}
// 엑셀 파일 생성 및 다운로드
try {
ExcelUtils.exportToExcelByRentention(retentionList,res);
}catch (IOException exception){
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
}
// int cnt = dateRange.size();
// for (LocalDate date : dateRange) {
// List<IndicatorsResponse.Dday> dDayList = new ArrayList<>();
// for (int i = 0; i < cnt; i++){
// IndicatorsResponse.Dday dDay = IndicatorsResponse.Dday.builder()
// .date("D+" + i)
// .dif("0%")
// .build();
// dDayList.add(dDay);
// }
// cnt -- ;
// IndicatorsResponse.Retention retention = IndicatorsResponse.Retention.builder()
// .date(date)
// .dDay(dDayList)
// .build();
// retentionList.add(retention);
// }
// // 엑셀 파일 생성 및 다운로드
// try {
// ExcelUtils.exportToExcelByRentention(retentionList,res);
// }catch (IOException exception){
// throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
// }
}
// 유저 지표 Retention

View File

@@ -18,6 +18,8 @@ public class AdminConstants {
public static final String MONGO_DB_COLLECTION_HISTORY_LOG = "historyLog";
public static final String MONGO_DB_COLLECTION_CURRENCY = "currency";
public static final String MONGO_DB_COLLECTION_ITEM = "item";
public static final String MONGO_DB_COLLECTION_CREATE = "userCreate";
public static final String MONGO_DB_COLLECTION_LOGIN = "userLogin";
public static final String MONGO_DB_KEY_LOGTIME = "logTime";
public static final String MONGO_DB_KEY_LOGMONTH = "logMonth";

View File

@@ -541,16 +541,16 @@ public class ExcelUtils {
int rowIndex = 1; // 시작 행 인덱스
// 두 번째 라인
for (IndicatorsResponse.Retention retention : list){
Row row = sheet.createRow(rowIndex++);
row.createCell(0).setCellValue("ALL");
List<IndicatorsResponse.Dday> dDay = retention.getDDay();
row.createCell(1).setCellValue(retention.getDate().toString());
for (int j = 0; j < dDay.size(); j++) {
row.createCell(j+2).setCellValue(dDay.get(j).getDif());
}
}
// for (IndicatorsResponse.Retention retention : list){
// Row row = sheet.createRow(rowIndex++);
// row.createCell(0).setCellValue("ALL");
// List<IndicatorsResponse.Dday> dDay = retention.getDDay();
// row.createCell(1).setCellValue(retention.getDate().toString());
// for (int j = 0; j < dDay.size(); j++) {
// row.createCell(j+2).setCellValue(dDay.get(j).getDif());
// }
//
// }
//cell 머지
sheet.addMergedRegion(CellRangeAddress.valueOf("A2:A"+(list.size()+1)));