검색기능 수정
This commit is contained in:
@@ -1546,16 +1546,7 @@ export class TableManagementService {
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Entity 조인 데이터 조회 실패: ${tableName}`, error);
|
||||
|
||||
// 에러 발생 시 기본 데이터 반환
|
||||
const basicResult = await this.getTableData(tableName, options);
|
||||
return {
|
||||
data: basicResult.data,
|
||||
total: basicResult.total,
|
||||
page: options.page,
|
||||
size: options.size,
|
||||
totalPages: Math.ceil(basicResult.total / options.size),
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1582,7 +1573,7 @@ export class TableManagementService {
|
||||
orderBy,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
).query;
|
||||
|
||||
// 카운트 쿼리
|
||||
const countQuery = entityJoinService.buildCountQuery(
|
||||
@@ -1650,8 +1641,178 @@ export class TableManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
// 기본 데이터 조회
|
||||
const basicResult = await this.getTableData(tableName, options);
|
||||
// Entity 조인 컬럼 검색이 있는지 확인 (기본 조인 + 추가 조인 컬럼 모두 포함)
|
||||
const allEntityColumns = [
|
||||
...joinConfigs.map((config) => config.aliasColumn),
|
||||
// 추가 조인 컬럼들도 포함 (writer_dept_code, company_code_status 등)
|
||||
...joinConfigs.flatMap((config) => {
|
||||
const additionalColumns = [];
|
||||
// writer -> writer_dept_code 패턴
|
||||
if (config.sourceColumn === "writer") {
|
||||
additionalColumns.push("writer_dept_code");
|
||||
}
|
||||
// company_code -> company_code_status 패턴
|
||||
if (config.sourceColumn === "company_code") {
|
||||
additionalColumns.push("company_code_status");
|
||||
}
|
||||
return additionalColumns;
|
||||
}),
|
||||
];
|
||||
|
||||
const hasEntitySearch =
|
||||
options.search &&
|
||||
Object.keys(options.search).some((key) =>
|
||||
allEntityColumns.includes(key)
|
||||
);
|
||||
|
||||
if (hasEntitySearch) {
|
||||
const entitySearchKeys = options.search
|
||||
? Object.keys(options.search).filter((key) =>
|
||||
allEntityColumns.includes(key)
|
||||
)
|
||||
: [];
|
||||
logger.info(
|
||||
`🔍 Entity 조인 컬럼 검색 감지: ${entitySearchKeys.join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
let basicResult;
|
||||
|
||||
if (hasEntitySearch) {
|
||||
// Entity 조인 컬럼으로 검색하는 경우 SQL JOIN 방식 사용
|
||||
logger.info("🔍 Entity 조인 컬럼 검색 감지, SQL JOIN 방식으로 전환");
|
||||
|
||||
try {
|
||||
// 테이블 컬럼 정보 조회
|
||||
const columns = await this.getTableColumns(tableName);
|
||||
const selectColumns = columns.data.map((col: any) => col.column_name);
|
||||
|
||||
// Entity 조인 컬럼 검색을 위한 WHERE 절 구성
|
||||
const whereConditions: string[] = [];
|
||||
const entitySearchColumns: string[] = [];
|
||||
|
||||
// Entity 조인 쿼리 생성하여 별칭 매핑 얻기
|
||||
const joinQueryResult = entityJoinService.buildJoinQuery(
|
||||
tableName,
|
||||
joinConfigs,
|
||||
selectColumns,
|
||||
"", // WHERE 절은 나중에 추가
|
||||
options.sortBy
|
||||
? `main.${options.sortBy} ${options.sortOrder || "ASC"}`
|
||||
: undefined,
|
||||
options.size,
|
||||
(options.page - 1) * options.size
|
||||
);
|
||||
|
||||
const aliasMap = joinQueryResult.aliasMap;
|
||||
logger.info(
|
||||
`🔧 [검색] 별칭 매핑 사용: ${Array.from(aliasMap.entries())
|
||||
.map(([table, alias]) => `${table}→${alias}`)
|
||||
.join(", ")}`
|
||||
);
|
||||
|
||||
if (options.search) {
|
||||
for (const [key, value] of Object.entries(options.search)) {
|
||||
const joinConfig = joinConfigs.find(
|
||||
(config) => config.aliasColumn === key
|
||||
);
|
||||
|
||||
if (joinConfig) {
|
||||
// 기본 Entity 조인 컬럼인 경우: 조인된 테이블의 표시 컬럼에서 검색
|
||||
const alias = aliasMap.get(joinConfig.referenceTable);
|
||||
whereConditions.push(
|
||||
`${alias}.${joinConfig.displayColumn} ILIKE '%${value}%'`
|
||||
);
|
||||
entitySearchColumns.push(
|
||||
`${key} (${joinConfig.referenceTable}.${joinConfig.displayColumn})`
|
||||
);
|
||||
logger.info(
|
||||
`🎯 Entity 조인 검색: ${key} → ${joinConfig.referenceTable}.${joinConfig.displayColumn} LIKE '%${value}%' (별칭: ${alias})`
|
||||
);
|
||||
} else if (key === "writer_dept_code") {
|
||||
// writer_dept_code: user_info.dept_code에서 검색
|
||||
const userAlias = aliasMap.get("user_info");
|
||||
whereConditions.push(
|
||||
`${userAlias}.dept_code ILIKE '%${value}%'`
|
||||
);
|
||||
entitySearchColumns.push(`${key} (user_info.dept_code)`);
|
||||
logger.info(
|
||||
`🎯 추가 Entity 조인 검색: ${key} → user_info.dept_code LIKE '%${value}%' (별칭: ${userAlias})`
|
||||
);
|
||||
} else if (key === "company_code_status") {
|
||||
// company_code_status: company_info.status에서 검색
|
||||
const companyAlias = aliasMap.get("company_info");
|
||||
whereConditions.push(
|
||||
`${companyAlias}.status ILIKE '%${value}%'`
|
||||
);
|
||||
entitySearchColumns.push(`${key} (company_info.status)`);
|
||||
logger.info(
|
||||
`🎯 추가 Entity 조인 검색: ${key} → company_info.status LIKE '%${value}%' (별칭: ${companyAlias})`
|
||||
);
|
||||
} else {
|
||||
// 일반 컬럼인 경우: 메인 테이블에서 검색
|
||||
whereConditions.push(`main.${key} ILIKE '%${value}%'`);
|
||||
logger.info(
|
||||
`🔍 일반 컬럼 검색: ${key} → main.${key} LIKE '%${value}%'`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const whereClause = whereConditions.join(" AND ");
|
||||
const orderBy = options.sortBy
|
||||
? `main.${options.sortBy} ${options.sortOrder === "desc" ? "DESC" : "ASC"}`
|
||||
: "";
|
||||
|
||||
// 페이징 계산
|
||||
const offset = (options.page - 1) * options.size;
|
||||
|
||||
// SQL JOIN 쿼리 실행
|
||||
const joinResult = await this.executeJoinQuery(
|
||||
tableName,
|
||||
joinConfigs,
|
||||
selectColumns,
|
||||
whereClause,
|
||||
orderBy,
|
||||
options.size,
|
||||
offset,
|
||||
startTime
|
||||
);
|
||||
|
||||
return joinResult;
|
||||
} catch (joinError) {
|
||||
logger.error(
|
||||
`Entity 조인 검색 실패, 캐시 방식으로 폴백: ${tableName}`,
|
||||
joinError
|
||||
);
|
||||
|
||||
// Entity 조인 검색 실패 시 Entity 조인 컬럼을 제외한 검색 조건으로 캐시 방식 사용
|
||||
const fallbackOptions = { ...options };
|
||||
if (options.search) {
|
||||
const filteredSearch: Record<string, any> = {};
|
||||
|
||||
// Entity 조인 컬럼을 제외한 검색 조건만 유지
|
||||
for (const [key, value] of Object.entries(options.search)) {
|
||||
const isEntityColumn = joinConfigs.some(
|
||||
(config) => config.aliasColumn === key
|
||||
);
|
||||
if (!isEntityColumn) {
|
||||
filteredSearch[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
fallbackOptions.search = filteredSearch;
|
||||
logger.info(
|
||||
`🔄 Entity 조인 에러 시 검색 조건 필터링: ${Object.keys(filteredSearch).join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
basicResult = await this.getTableData(tableName, fallbackOptions);
|
||||
}
|
||||
} else {
|
||||
// Entity 조인 컬럼 검색이 없는 경우 기존 캐시 방식 사용
|
||||
basicResult = await this.getTableData(tableName, options);
|
||||
}
|
||||
|
||||
// Entity 값들을 캐시에서 룩업하여 변환
|
||||
const enhancedData = basicResult.data.map((row: any) => {
|
||||
|
||||
Reference in New Issue
Block a user