SEARCH 명령어

SEARCH 명령어

search 명령어는 인덱스에서 문서를 검색해요. search 명령어는 PPL 쿼리에서 첫 번째 명령어로만 사용할 수 있어요.

출처: 문서

본문

search 명령어는 인덱스에서 문서를 검색해요. search 명령어는 PPL 쿼리에서 첫 번째 명령어로만 사용할 수 있어요.

구문 (Syntax)

search 명령어의 구문은 다음과 같아요:

search source=[<remote-cluster>:]<index> [<search-expression>]

매개변수 (Parameters)

search 명령어는 다음 매개변수를 지원해요.

매개변수 필수/선택 설명
<index> 필수 쿼리할 인덱스예요. 인덱스 이름에는 크로스 클러스터 검색을 위해 <remote-cluster>:(원격 클러스터 이름)을 앞에 붙일 수 있어요.
<search-expression> 선택 OpenSearch 쿼리 문자열 쿼리로 변환되는 검색 표현식이에요.

검색 표현식 (Search expression)

검색 표현식 구문은 다음을 지원해요:

  • 전문 검색(Full-text search): error 또는 "error message" – index.query.default_field 설정(기본값은 *, 모든 필드 지정)에 구성된 기본 필드를 검색해요. 자세한 내용은 기본 필드 구성(Default field configuration)을 참고해요.
  • 필드-값 비교(Field-value comparisons): field=value, field!=value, field>value, field>=value, field<value 또는 field<=value.
  • 시간 수정자(Time modifiers): earliest=timeModifier, latest=timeModifier – 암시적 @timestamp 필드를 사용해 시간 범위로 결과를 필터링해요. 자세한 내용은 시간 수정자(Time modifiers)를 참고해요.
  • 불리언 연산자(Boolean operators): AND, OR 또는 NOT. 기본값은 AND예요.
  • 괄호를 사용한 그룹화(Grouping using parentheses): (expression).
  • 여러 값을 위한 IN 연산자: field IN (value1, value2, value3).
  • 와일드카드(Wildcards): *(0개 이상의 문자), ?(정확히 1개 문자).

전문 검색 (Full-text search)

다른 PPL 명령어와 달리 search 명령어는 따옴표가 있는 문자열과 없는 문자열을 모두 지원해요. 따옴표가 없는 용어는 알파벳 숫자 문자, 하이픈, 밑줄, 와일드카드로 제한돼요. 그 외의 문자는 큰따옴표가 필요해요.

다음 쿼리는 두 구문 타입을 모두 보여줘요:

  • 따옴표 없음: search error, search user-123, search log_*
  • 따옴표 있음: search "error message", search "[email protected]"

필드 값 (Field values)

필드 값은 검색 텍스트와 동일한 따옴표 규칙을 따라요.

필드 값 구문의 예:

  • 따옴표 없음: status=active, code=ERR-401
  • 따옴표 있음: email="[email protected]", message="server error"

시간 수정자 (Time modifiers)

시간 수정자는 암시적 @timestamp 필드를 사용해 시간 범위로 검색 결과를 필터링해요. 시간 수정자는 다음 형식을 지원해요.

형식 구문 설명 예
현재 시간 now 또는 now() 현재 시간 earliest=now
절대 시간 MM/dd/yyyy:HH:mm:ss 또는 yyyy-MM-dd HH:mm:ss 특정 날짜와 시간 latest='2024-12-31 23:59:59'
Unix 타임스탬프 숫자 값 에포크 이후 초 latest=1754020060.123
상대 시간 [(+/-)<time_integer><time_unit>][@<round_to_unit>] 현재 시간 기준 시간 오프셋. 상대 시간 구성 요소(Relative time components) 참고 earliest=-7d, latest='+1d@d'
상대 시간 구성 요소 (Relative time components)

상대 시간 수정자는 결합할 수 있는 여러 구성 요소를 사용해요. 다음 표는 각 구성 요소를 설명해요.

구성 요소 구문 설명 예
시간 오프셋 + 또는 - 방향: +(미래) 또는 -(과거) +7d, -1h
시간 양 <time_integer><time_unit> 숫자 값 + 시간 단위 7d, 1h, 30m
단위로 반올림 @<round_to_unit> 가장 가까운 단위로 반올림 @d(일), @h(시간), @m(분)

다음은 일반적인 시간 수정자 패턴의 예시예요:

  • earliest=now – 현재 시간부터 시작.
  • latest='2024-12-31 23:59:59' – 특정 날짜와 시간에 종료.
  • earliest=-7d – 7일 전부터 시작.
  • latest='+1d@d' – 내일 시작 시점에 종료.
  • earliest='-1month@month' – 지난 달 시작부터 시작.
  • latest=1754020061 – Unix 타임스탬프 1754020061(2025년 8월 1일 03:47:41 UTC)에 종료.

search 명령어에서 시간 수정자를 사용할 때 다음 사항을 고려해요:

  • 열 이름 충돌(Column name conflicts): 데이터에 earliest 또는 latest라는 열이 있으면 백틱을 사용해 일반 필드로 접근해요 (예: `earliest`="value") 시간 수정자 구문과의 충돌을 피해요.
  • 시간 반올림 구문(Time round syntax): 연결된 시간 오프셋이 있는 시간 수정자는 올바른 쿼리 파싱을 위해 따옴표로 감싸야 해요 (예: latest='+1d@month-10h').

기본 필드 구성 (Default field configuration)

필드를 지정하지 않고 검색을 수행하면 index.query.default_field 인덱스 설정에 구성된 기본 필드를 사용해요. 기본적으로 이 값은 *로 설정되어 모든 필드를 검색해요.

기본 필드 설정을 검색하려면 다음 요청을 사용해요:

GET /accounts/_settings/index.query.default_field

기본 필드 설정을 수정하려면 다음 요청을 사용해요:

PUT /accounts/_settings
{
  "index.query.default_field": "firstname,lastname,email"
}

필드 타입별 검색 동작 (Search behavior by field type)

필드 타입마다 특정 검색 기능과 제한 사항이 있어요. 다음 표는 각 필드 타입에서 검색 표현식이 어떻게 작동하는지 요약해요.

필드 타입 지원 연산 예 제한 사항
텍스트 전문 검색, 구문 검색 search message="error occurred" source=logs 와일드카드는 분석 후 용어에 적용되며 전체 필드 값에는 적용되지 않음
키워드 정확 일치, 와일드카드 패턴 search status="ACTIVE" source=logs 텍스트 분석 없음; 일치는 대소문자 구분
숫자 범위 쿼리, 정확 일치, IN 연산자 search age>=18 AND balance<50000 source=accounts 와일드카드 또는 텍스트 검색 미지원
날짜 범위 쿼리, 정확 일치, IN 연산자 search timestamp>="2024-01-01" source=logs 인덱스 매핑 날짜 형식을 따라야 함; 와일드카드 미지원
불리언 정확 일치, true/false 값, IN 연산자 search active=true source=users 와일드카드 또는 범위 쿼리 미지원
IP 정확 일치, CIDR 표기 search client_ip="192.168.1.0/24" source=logs 부분 IP 와일드카드 일치 미지원. 와일드카드 검색은 키워드가 있는 멀티필드 사용: search ip_address.keyword='1*' source=logs 또는 WHERE 절: source=logs | where cast(ip_address as string) like '1%'

다양한 필드 타입으로 작업할 때 다음 성능 최적화를 고려해요:

  • 각 필드 타입에는 특정 검색 기능과 제한 사항이 있어요. 수집 중에 부적절한 필드 타입을 선택하면 성능과 쿼리 정확도에 부정적인 영향을 줄 수 있어요.
  • 비키워드 필드에서 와일드카드 검색을 하려면 성능을 개선하기 위해 키워드 하위 필드를 만들어요. 예를 들어 text 타입의 message 필드에서 와일드카드 검색을 하려면 message.keyword 필드를 추가해요.

예제 1: 모든 데이터 가져오기

인덱스에서 모든 문서를 검색해요:

source=otellogs
| head 3

쿼리는 다음과 같은 결과를 반환해요:

spanId traceId @timestamp instrumentationScope severityText resource flags attributes droppedAttributesCount severityNumber time body
span0001 abcd1234efgh5678 2024-02-01 09:10:00 {‘name’: ‘@opentelemetry/instrumentation-http’, ‘droppedAttributesCount’: 0, ‘version’: ‘0.57.0’} INFO {‘attributes’: {‘service’: {‘name’: ‘frontend’}, ‘host’: {‘name’: ‘frontend-6b7b4c9f-x2kl9’}}, ‘droppedAttributesCount’: 0} 0 {} 0 9 2024-02-01 09:10:00 [2024-02-01T09:10:00.123Z] “GET /api/products HTTP/1.1” 200 - 1024 45 frontend-6b7b4c9f-x2kl9
span0002 abcd1234efgh5678 2024-02-01 09:11:00 {‘name’: ‘Microsoft.Extensions.Hosting’, ‘droppedAttributesCount’: 0, ‘version’: ‘9.0.0’} INFO {‘attributes’: {‘service’: {‘name’: ‘cart’}, ‘host’: {‘name’: ‘cart-5d8f7b-mk29s’}}, ‘droppedAttributesCount’: 0} 0 {} 0 9 2024-02-01 09:11:00 Order #1234 placed successfully by user U100
span0003 abcd1234efgh5678 2024-02-01 09:12:00 {‘name’: ‘go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc’, ‘droppedAttributesCount’: 0, ‘version’: ‘0.49.0’} WARN {‘attributes’: {‘service’: {‘name’: ‘product-catalog’}, ‘host’: {‘name’: ‘productcatalog-7c9d-zn4p2’}}, ‘droppedAttributesCount’: 0} 0 {} 0 13 2024-02-01 09:12:00 Slow query detected: SELECT * FROM products WHERE category = ‘electronics’ took 3200ms

예제 2: 텍스트 검색하기

기본 텍스트 검색에는 따옴표가 없는 단일 용어를 사용해요:

search ERROR source=otellogs
| sort `resource.attributes.service.name`
| fields severityText, body
| head 1

쿼리는 다음과 같은 결과를 반환해요:

severityText body
ERROR NullPointerException in CheckoutService.placeOrder at line 142

다중 단어 정확 일치를 위한 구문 검색에는 따옴표가 필요해요:

search "Payment failed" source=otellogs
| sort `resource.attributes.service.name` | fields body | head 1

쿼리는 다음과 같은 결과를 반환해요:

body
Payment failed: connection timeout to payment gateway after 30000ms

여러 검색 용어(따옴표 없는 문자열 리터럴)는 자동으로 AND 연산자로 결합돼요:

search connection timeout source=otellogs
| fields body

쿼리는 다음과 같은 결과를 반환해요:

body
Payment failed: connection timeout to payment gateway after 30000ms

search connection timeout은 search connection AND timeout과 동일해요.

결합된 구문 및 불리언 검색

더 정밀한 검색을 위해 따옴표가 있는 구문을 불리언 연산자와 결합해요:

search "connection timeout" OR "heap space" source=otellogs
| sort `resource.attributes.service.name`
| fields body

쿼리는 다음과 같은 결과를 반환해요:

body
Payment failed: connection timeout to payment gateway after 30000ms
Out of memory: Java heap space - shutting down pod payment-6f8d4b-ht7q3

예제 3: 불리언 논리와 연산자 우선순위

다음 쿼리는 불리언 연산자와 우선순위를 보여줘요.

불리언 연산자

OR을 사용해 지정된 조건 중 하나라도 포함하는 문서를 일치시켜요:

search severityText="ERROR" OR severityText="WARN" source=otellogs
| sort severityNumber, `resource.attributes.service.name`
| fields severityText, `resource.attributes.service.name`

쿼리는 다음과 같은 결과를 반환해요:

severityText resource.attributes.service.name
WARN frontend-proxy
WARN frontend-proxy
WARN product-catalog
WARN product-catalog
ERROR checkout
ERROR checkout
ERROR frontend-proxy
ERROR payment
ERROR payment
ERROR product-catalog
ERROR recommendation

모든 조건이 일치해야 하는 경우 AND로 조건을 결합해요:

search severityText="INFO" AND `resource.attributes.service.name`="cart-service" source=otellogs
| fields body
| head 1

쿼리는 다음과 같은 결과를 반환해요:

body
Order #1234 placed successfully by user U100

연산자 우선순위 (Operator precedence)

연산자는 다음 우선순위로 평가돼요:

Parentheses > NOT > OR > AND

다음 쿼리는 연산자 우선순위를 보여줘요:

search severityText="ERROR" OR severityText="WARN" AND severityNumber>15 source=otellogs
| sort @timestamp
| fields severityText, severityNumber
| head 2

앞의 표현식은 (severityText="ERROR" OR severityText="WARN") AND severityNumber>15로 평가돼요. 쿼리는 다음과 같은 결과를 반환해요:

severityText severityNumber
ERROR 17
ERROR 17

예제 4: NOT과 != 의미 비교하기

!=와 NOT 연산자는 모두 필드 값이 지정된 값과 같지 않은 문서를 찾아요. 그러나 != 연산자는 null이나 누락된 필드를 포함한 문서를 제외하고, NOT 연산자는 포함해요. 다음 쿼리는 대부분의 레코드에서 null인 instrumentationScope.name을 사용해 이 차이를 보여줘요.

!= 연산자

null 값을 제외해요 — 필드가 존재하고 지정된 값이 아닌 행만 반환해요:

search instrumentationScope.name!="@opentelemetry/instrumentation-http" source=otellogs
| fields instrumentationScope.name

쿼리는 다음과 같은 결과를 반환해요:

instrumentationScope.name
Microsoft.Extensions.Hosting

NOT 연산자

null 값을 포함해요 — 필드가 null이거나 지정된 값이 아닌 행을 반환해요:

search NOT instrumentationScope.name="@opentelemetry/instrumentation-http" source=otellogs
| fields instrumentationScope.name
| head 5

쿼리는 다음과 같은 결과를 반환해요:

instrumentationScope.name
Microsoft.Extensions.Hosting
null
null
null
null

예제 5: 범위 쿼리하기

비교 연산자(>, <, >=, <=)를 사용해 특정 범위 내의 숫자 및 날짜 필드를 필터링해요. 범위 쿼리는 나이, 가격, 타임스탬프 또는 숫자 지표로 필터링할 때 특히 유용해요:

search severityNumber>13 AND severityNumber<=21 source=otellogs
| sort severityNumber, `resource.attributes.service.name`
| fields severityNumber
| head 3

쿼리는 다음과 같은 결과를 반환해요:

severityNumber
17
17
17

예제 6: 와일드카드 사용하기

다음 쿼리는 와일드카드 패턴 매칭을 보여줘요. 와일드카드 패턴에서 *는 0개 이상의 문자와 일치하고 ?는 정확히 1개 문자와 일치해요.

*를 사용해 용어 끝의 임의 개수 문자를 일치시켜요:

search severityText=ERR* source=otellogs
| sort severityNumber, `resource.attributes.service.name`
| fields severityText
| head 3

쿼리는 다음과 같은 결과를 반환해요:

severityText
ERROR
ERROR
ERROR

부분 일치를 찾기 위해 텍스트 필드 내에서도 와일드카드 검색이 작동해요:

search body=connection* source=otellogs
| sort `resource.attributes.service.name`
| fields body
| head 2

쿼리는 다음과 같은 결과를 반환해요:

body
Payment failed: connection timeout to payment gateway after 30000ms
Connection pool 80% utilized on database replica db-replica-02

특정 위치에서 정확히 1개 문자를 일치시키려면 ?를 사용해요:

search severityText="ERR?R" source=otellogs
| fields severityText, `resource.attributes.service.name`
| head 3

쿼리는 다음과 같은 결과를 반환해요:

severityText resource.attributes.service.name
ERROR payment
ERROR checkout
ERROR payment

예제 7: 서비스 이름 검색의 와일드카드 패턴

텍스트 또는 키워드 필드에서 검색할 때 와일드카드는 부분 일치를 가능하게 해요. 서비스 이름의 일부만 알 때 유용해요. 와일드카드는 패턴을 사용해 정확한 값을 일치시키는 키워드 필드에서 가장 잘 작동해요. 텍스트 필드에 와일드카드를 사용하면 분석 후 개별 토큰에 적용되므로 전체 필드 값이 아닌 토큰에 적용되어 예상치 못한 결과가 발생할 수 있어요. 키워드 필드의 와일드카드는 인덱싱 시 정규화되지 않는 한 대소문자를 구분해요.

선행 와일드카드(예: *-service)는 후행 와일드카드보다 쿼리 속도를 저하시킬 수 있어요.

서비스 이름의 시작만 알 때 서비스 로그를 찾아요:

search `resource.attributes.service.name`=payment* source=otellogs
| fields severityText, `resource.attributes.service.name`, body
| head 2

쿼리는 다음과 같은 결과를 반환해요:

severityText resource.attributes.service.name body
ERROR payment Payment failed: connection timeout to payment gateway after 30000ms
ERROR payment Out of memory: Java heap space - shutting down pod payment-6f8d4b-ht7q3

더 정밀한 필터링을 위해 와일드카드 패턴을 다른 조건과 결합해요:

search firstname=A* AND age>30 source=accounts
| fields firstname, age, city

쿼리는 다음과 같은 결과를 반환해요:

firstname age city
Amber 32 Brogan

예제 8: 필드 값 매칭

IN 연산자는 필드가 목록의 값과 일치하는지 효율적으로 확인해요. 같은 필드에 여러 OR 조건을 연결하는 것보다 간결하고 성능이 더 좋은 대안이에요.

필드가 미리 정의된 목록의 값과 일치하는지 확인해요:

search severityText IN ("ERROR", "WARN") source=otellogs
| fields severityText, `resource.attributes.service.name`

쿼리는 다음과 같은 결과를 반환해요:

severityText resource.attributes.service.name
WARN product-catalog
WARN product-catalog
WARN frontend-proxy
WARN frontend-proxy
ERROR payment
ERROR checkout
ERROR payment
ERROR frontend-proxy
ERROR recommendation
ERROR product-catalog
ERROR checkout

특정 숫자 severity 레벨의 오류를 찾기 위해 severityNumber로 로그를 필터링해요:

search severityNumber=17 source=otellogs
| fields body, `resource.attributes.service.name`

쿼리는 다음과 같은 결과를 반환해요:

body resource.attributes.service.name
Payment failed: connection timeout to payment gateway after 30000ms payment
NullPointerException in CheckoutService.placeOrder at line 142 checkout
Out of memory: Java heap space - shutting down pod payment-6f8d4b-ht7q3 payment
[2024-02-01T09:20:00.456Z] “POST /api/checkout HTTP/1.1” 503 - 0 30000 checkout-8d4f7b-mk2p9 frontend-proxy
Failed to process recommendation request: invalid product ID from 203.0.113.50 recommendation
Database primary node unreachable: connection refused to db-primary-01:5432 product-catalog
Kafka producer delivery failed: message too large for topic order-events (max 1048576 bytes) checkout

예제 9: 복잡한 표현식 사용하기

정교한 검색 쿼리를 만들려면 불리언 연산자와 괄호를 사용해 여러 조건을 결합해요:

search (severityText="ERROR" OR severityText="WARN") AND severityNumber>13 source=otellogs
| sort severityNumber, `resource.attributes.service.name`
| fields severityText
| head 3

쿼리는 다음과 같은 결과를 반환해요:

severityText
ERROR
ERROR
ERROR

예제 10: 시간 수정자 사용하기

시간 수정자는 암시적 @timestamp 필드를 사용해 시간 범위로 검색 결과를 필터링해요. 정밀한 시간 필터링을 위해 다양한 시간 형식을 지원해요.

절대 시간 필터링

절대 타임스탬프를 사용해 특정 시간 창 내의 로그를 필터링해요:

search earliest='2024-02-01 09:13:00' latest='2024-02-01 09:16:00' source=otellogs
| sort severityNumber
| fields `@timestamp`, severityText

쿼리는 다음과 같은 결과를 반환해요:

@timestamp severityText
2024-02-01 09:14:00 DEBUG
2024-02-01 09:16:00 INFO
2024-02-01 09:13:00 ERROR
2024-02-01 09:15:00 ERROR

상대 시간 필터링

30초 전 이전에 발생한 사건 같은 상대 시간 표현식을 사용해 로그를 필터링해요:

search latest=-30s source=otellogs
| sort severityNumber
| fields `@timestamp`, severityText
| head 3

쿼리는 다음과 같은 결과를 반환해요:

@timestamp severityText
2024-02-01 09:14:00 DEBUG
2024-02-01 09:21:00 DEBUG
2024-02-01 09:28:00 DEBUG

시간 반올림

현재 분 시작 이전의 사건과 같은 시간 경계를 기준으로 이벤트를 필터링하려면 시간 반올림 표현식을 사용해요:

search latest='@m' source=otellogs
| sort severityNumber
| fields `@timestamp`, severityText
| head 2

쿼리는 다음과 같은 결과를 반환해요:

@timestamp severityText
2024-02-01 09:14:00 DEBUG
2024-02-01 09:21:00 DEBUG

Unix 타임스탬프 필터링

정밀한 시간 범위를 위해 Unix 에포크 타임스탬프를 사용해 로그를 필터링해요:

search earliest=1706778600 latest=1706778960 source=otellogs
| sort severityNumber
| fields `@timestamp`, severityText

쿼리는 다음과 같은 결과를 반환해요:

@timestamp severityText
2024-02-01 09:14:00 DEBUG
2024-02-01 09:10:00 INFO
2024-02-01 09:11:00 INFO
2024-02-01 09:16:00 INFO
2024-02-01 09:12:00 WARN
2024-02-01 09:13:00 ERROR
2024-02-01 09:15:00 ERROR

특수 문자 이스케이프하기 (Escaping special characters)

특수 문자는 항상 이스케이프해야 하는지 또는 리터럴 값을 검색할 때만 이스케이프해야 하는지에 따라 두 가지 범주로 나뉘어요:

  • 다음 문자는 리터럴로 해석하려면 항상 이스케이프해야 해요: 백슬래시(\) – \\로 이스케이프. 큰따옴표(") – 따옴표가 있는 문자열 내에서 \"로 이스케이프.
  • 다음 문자는 기본적으로 와일드카드로 작동하며 리터럴로 일치시키려는 경우에만 이스케이프해야 해요: 애스터리스크(*) – 와일드카드 매칭에는 *로 사용하고, 리터럴 애스터리크에는 \*로 이스케이프. 물음표(?) – 와일드카드 매칭에는 ?로 사용하고, 리터럴 물음표에는 \?로 이스케이프.

다음 표는 와일드카드와 리터럴 문자 매칭을 비교해요.

의도 PPL 구문 결과
와일드카드 검색 field=user* user, user123, userABC 일치
리터럴 user* field="user\*" 오직 user*만 일치
와일드카드 검색 field=log? log1, logA, logs 일치
리터럴 log? field="log\?" 오직 log?만 일치

더 알아보기 (Learn more)