2021년 10월 11일 월요일

엘라스틱 Runtime field - 4th

읽기 스키마 맛을 본 뒤론 가급적 런타임 필드를 사용하려고 한다. 다음은 URI 필드에서 url과 변수 정보를 런타임 필드로 추출하는 구문.
PUT test/_mapping
{
  "runtime": {
    "url": {
      "type": "keyword",
      "script": "emit(grok('(?<url>[^?]+)').extract(doc['uri.keyword'].value).url)"
    },
    "param": {
      "type": "keyword",
      "script": "emit(grok('[^?]+\\\\??(?<param>.*)').extract(doc['uri.keyword'].value).param)"
    }
  }
}


유효한 값이 아닌, empty 값을 갖는 필드가 존재하면 나중에 골치 아파질 수 있다. 값이 없는 필드를 만들고 싶지 않다면 조건을 줘야 함.
PUT test/_mapping
{
  "runtime": {
    "url": {
      "type": "keyword",
      "script": "emit(grok('(?<url>[^?]+)').extract(doc['uri.keyword'].value).url)"
    },
    "param": {
      "type": "keyword",
      "script": """
        if (doc['uri.keyword'].value.contains('?')) {
          emit(grok('.*\\?(?<param>.*)').extract(doc['uri.keyword'].value).param)
        }
      """
    }
  }
}


여러 개의 필드를 한 방(?)에 만들고 싶다면

원하는 만큼 캡쳐그룹을 지정해도 grok().extract().capture_group_name 구문은 한 번에 하나의 캡쳐그룹만을 필드로 추출할 수 있다. 이때 엘라스틱은 composite 타입을 이용해서 멀티 생성을 지원함.
PUT test/_mapping
{
  "runtime": {
    "url": {
      "type": "composite",
      "script": """
        if (doc['uri.keyword'].value.contains('?')) {
          emit(grok('(?<url>[^?]+)\\??(?<param>.*)').extract(doc['uri.keyword'].value))
        } else {
          emit(grok('(?<url>.*)').extract(doc['uri.keyword'].value))
        }
      """,
      "fields": {
        "url": {
          "type": "keyword"
        },
        "param": {
          "type": "keyword"
        }
      }
    }
  }
}


장점인지 단점인지는 모르겠지만 '부모-자식' 구조의 필드만 만들 수 있다. 더 편한지도 잘 모르겠음 dissect 필터도 사용 가능.
PUT test/_mapping
{
  "runtime": {
    "url": {
      "type": "composite",
      "script": """
        if (doc['uri.keyword'].value.contains('?')) {
          emit(dissect('%{url}?%{param}').extract(doc['uri.keyword'].value))
        } else {
          emit(dissect('%{url}').extract(doc['uri.keyword'].value))
        }
      """,
      "fields": {
        "url": {
          "type": "keyword"
        },
        "param": {
          "type": "keyword"
        }
      }
    }
  }
}

당연히 스플렁크도 멀티 생성을 지원한다. 예외처리도 필요 없고 간단.
| makeresults
| eval uri="/path/a.php?a=1 /phth/b.php?b=2&c=3 /path/c.php"
| makemv delim=" " uri
| mvexpand uri
| rex field=uri "(?<url>[^?]*)(\?(?<param>[^|]*))?"
| table uri, url, param


관련 글

댓글 없음:

댓글 쓰기

크리에이티브 커먼즈 라이선스