Commit e4108146 authored by platyhouse's avatar platyhouse

# 필드별 검색 기능 추가 및 매핑 정보 출력 개선

## 필드 검색 기능 추가

### 새로운 검색 옵션 지원
- ptyElasticGetIndex.php: --필드명=검색어 형태의 필드별 검색 옵션 추가
  - 예약된 옵션(elastic, limit, verbose, help)을 제외한 옵션을 필드 검색으로 처리
  - wildcard 패턴 지원 (*검색어, 검색어*, *검색어*)
  - wildcard 없는 경우 term + match 쿼리 조합으로 keyword/text 필드 모두 검색

### 쿼리 생성 로직 개선
- ptyElasticGetIndex.php: bool 쿼리의 must 절을 사용한 복합 검색 지원
  - 일반 검색어와 필드 검색을 AND 조건으로 결합
  - 단일 조건일 때는 불필요한 bool 래핑 생략

## 매핑 정보 출력 개선

### 필드 정보 상세화
- ptyElasticGetIndex.php: 매핑 정보에 analyzer, search_analyzer 컬럼 추가
  - 기존 필드명, 타입에 추가로 분석기 정보 표시
  - 테이블 폭 60자에서 100자로 확장

## 도움말 업데이트

- ptyElasticGetIndex.php: 필드 검색 사용법 및 예시 추가
  - wildcard 패턴 설명 포함
  - 복합 검색 예시 추가 (--law_name, --lw_category)
parent c305821b
...@@ -22,6 +22,17 @@ $elasticSection = $options['elastic'] ?? 'default'; ...@@ -22,6 +22,17 @@ $elasticSection = $options['elastic'] ?? 'default';
$limit = isset($options['limit']) ? (int)$options['limit'] : 50; $limit = isset($options['limit']) ? (int)$options['limit'] : 50;
$verbose = isset($options['verbose']); $verbose = isset($options['verbose']);
// 예약된 옵션 (필드 검색에서 제외)
$reservedOptions = ['elastic', 'limit', 'verbose', 'help'];
// 필드 검색 옵션 추출 (--필드명=검색어)
$fieldSearches = [];
foreach ($options as $key => $value) {
if (!in_array($key, $reservedOptions) && $value !== true) {
$fieldSearches[$key] = $value;
}
}
// 도움말 또는 인덱스명 확인 // 도움말 또는 인덱스명 확인
if (empty($positionalArgs) || isset($options['help'])) { if (empty($positionalArgs) || isset($options['help'])) {
echo "사용법: {$argv[0]} <index_name> [search_term1] [search_term2] ... [옵션]\n"; echo "사용법: {$argv[0]} <index_name> [search_term1] [search_term2] ... [옵션]\n";
...@@ -32,6 +43,12 @@ if (empty($positionalArgs) || isset($options['help'])) { ...@@ -32,6 +43,12 @@ if (empty($positionalArgs) || isset($options['help'])) {
echo " --verbose 상세 로그 출력\n"; echo " --verbose 상세 로그 출력\n";
echo " --help 도움말 출력\n"; echo " --help 도움말 출력\n";
echo "\n"; echo "\n";
echo "필드 검색:\n";
echo " --필드명=검색어 특정 필드에서 검색 (wildcard 지원)\n";
echo " *검색어 검색어로 끝나는 값\n";
echo " 검색어* 검색어로 시작하는 값\n";
echo " *검색어* 검색어가 포함된 값\n";
echo "\n";
echo "예시:\n"; echo "예시:\n";
echo " {$argv[0]} my_index\n"; echo " {$argv[0]} my_index\n";
echo " {$argv[0]} my_index --limit=5\n"; echo " {$argv[0]} my_index --limit=5\n";
...@@ -39,8 +56,10 @@ if (empty($positionalArgs) || isset($options['help'])) { ...@@ -39,8 +56,10 @@ if (empty($positionalArgs) || isset($options['help'])) {
echo " {$argv[0]} my_index \"전기통신\" \"제11조\"\n"; echo " {$argv[0]} my_index \"전기통신\" \"제11조\"\n";
echo " {$argv[0]} my_index \"keyword AND another\"\n"; echo " {$argv[0]} my_index \"keyword AND another\"\n";
echo " {$argv[0]} my_index --elastic=production --limit=10\n"; echo " {$argv[0]} my_index --elastic=production --limit=10\n";
echo " {$argv[0]} my_index --law_name=\"*민법*\"\n";
echo " {$argv[0]} my_index --law_name=\"민법*\" --lw_category=\"법률\"\n";
echo "\n"; echo "\n";
echo "Note: Multiple search terms are combined with AND operator\n"; echo "Note: Multiple search terms and field searches are combined with AND operator\n";
echo "\n"; echo "\n";
echo "설정 파일: ~/.ptyElasticConfig.ini\n"; echo "설정 파일: ~/.ptyElasticConfig.ini\n";
echo ptyElasticConfig::getConfigExample() . "\n"; echo ptyElasticConfig::getConfigExample() . "\n";
...@@ -162,12 +181,14 @@ try { ...@@ -162,12 +181,14 @@ try {
if (isset($mappingData[$indexName]['mappings']['properties'])) { if (isset($mappingData[$indexName]['mappings']['properties'])) {
$properties = $mappingData[$indexName]['mappings']['properties']; $properties = $mappingData[$indexName]['mappings']['properties'];
printf("%-40s %-15s\n", "필드명", "타입"); printf("%-40s %-15s %-20s %-20s\n", "필드명", "타입", "analyzer", "search_analyzer");
echo str_repeat("-", 60) . "\n"; echo str_repeat("-", 100) . "\n";
foreach ($properties as $fieldName => $fieldInfo) { foreach ($properties as $fieldName => $fieldInfo) {
$type = $fieldInfo['type'] ?? 'object'; $type = $fieldInfo['type'] ?? 'object';
printf("%-40s %-15s\n", substr($fieldName, 0, 40), $type); $analyzer = $fieldInfo['analyzer'] ?? '-';
$searchAnalyzer = $fieldInfo['search_analyzer'] ?? '-';
printf("%-40s %-15s %-20s %-20s\n", substr($fieldName, 0, 40), $type, $analyzer, $searchAnalyzer);
} }
$totalFields = count($properties); $totalFields = count($properties);
...@@ -176,23 +197,71 @@ try { ...@@ -176,23 +197,71 @@ try {
echo "\n"; echo "\n";
// 5. TOP N 문서 조회 // 5. TOP N 문서 조회
if ($searchQuery) { $hasSearch = $searchQuery || !empty($fieldSearches);
echo "[ 5. 검색 결과 TOP {$limit} (검색어: \"$searchQuery\") ]\n"; if ($hasSearch) {
$searchDesc = [];
if ($searchQuery) {
$searchDesc[] = "검색어: \"$searchQuery\"";
}
foreach ($fieldSearches as $field => $value) {
$searchDesc[] = "$field: \"$value\"";
}
echo "[ 5. 검색 결과 TOP {$limit} (" . implode(', ', $searchDesc) . ") ]\n";
} else { } else {
echo "[ 5. 샘플 문서 TOP {$limit} ]\n"; echo "[ 5. 샘플 문서 TOP {$limit} ]\n";
} }
echo str_repeat("-", 100) . "\n"; echo str_repeat("-", 100) . "\n";
// 검색 쿼리 생성 // 검색 쿼리 생성
$mustClauses = [];
// 일반 검색어 (positional args)
if ($searchQuery) { if ($searchQuery) {
$query = [ $mustClauses[] = [
'query_string' => [ 'query_string' => [
'query' => $searchQuery, 'query' => $searchQuery,
'default_operator' => 'AND' 'default_operator' => 'AND'
] ]
]; ];
} else { }
// 필드 검색 (--필드명=검색어)
foreach ($fieldSearches as $field => $value) {
// wildcard 포함 여부 확인
if (strpos($value, '*') !== false) {
$mustClauses[] = [
'wildcard' => [
$field => [
'value' => $value,
'case_insensitive' => true
]
]
];
} else {
// wildcard 없으면 term 쿼리 (keyword 필드) + match 쿼리 (text 필드) 동시 사용
$mustClauses[] = [
'bool' => [
'should' => [
['term' => [$field => $value]],
['match' => [$field => $value]]
],
'minimum_should_match' => 1
]
];
}
}
// 최종 쿼리 생성
if (empty($mustClauses)) {
$query = ['match_all' => (object)[]]; $query = ['match_all' => (object)[]];
} elseif (count($mustClauses) === 1) {
$query = $mustClauses[0];
} else {
$query = [
'bool' => [
'must' => $mustClauses
]
];
} }
$searchBody = [ $searchBody = [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment