다음은 url 필드에서 추출한 파일과 확장자 정보를 이용해서 런타임 필드를 만드는 painless 스크립트. 정보 추출 범위는 .을 포함한 url만으로 제한했다.
PUT iislog/_mapping{ "runtime": { "file": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = grok('.*\\/(?<file>.*)').extract(doc['url'].value).file; emit(result); } """ }, "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = doc['url'].value.splitOnToken('.')[-1]; emit(result); } """ } }}
잘 됨.
변수 길이도 측정해보자
param_len 필드를 추가하는 스크립트 추가. 숫자값을 저장할 필드이므로 keyword가 아닌 long 타입으로 지정. 정보 추출 범위는 값이 존재하는 필드만으로 제한했다.
PUT iislog/_mapping{ "runtime": { "file": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = grok('.*\\/(?<file>.*)').extract(doc['url'].value).file; emit(result); } """ }, "ext": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = doc['url'].value.splitOnToken('.')[-1]; emit(result); } """ }, "param_len": { "type": "long", "script": """ if (!doc['param'].empty) { String result = doc['param'].value.length(); emit(result); } """ } }}
그런데 에러 발생.
{ "error" : { "root_cause" : [ { "type" : "script_exception", "reason" : "compile error", "script_stack" : [ "... length();\n emit(result);\n }\n ", " ^---- HERE" ], "script" : "\n if (!doc['param'].empty) {\n String result = doc['param'].value.length();\n emit(result);\n }\n ", "lang" : "painless", "position" : { "offset" : 106, "start" : 81, "end" : 131 } } ], "type" : "mapper_parsing_exception", "reason" : "Failed to parse mapping [_doc]: compile error", "caused_by" : { "type" : "script_exception", "reason" : "compile error", "script_stack" : [ "... length();\n emit(result);\n }\n ", " ^---- HERE" ], "script" : "\n if (!doc['param'].empty) {\n String result = doc['param'].value.length();\n emit(result);\n }\n ", "lang" : "painless", "position" : { "offset" : 106, "start" : 81, "end" : 131 }, "caused_by" : { "type" : "class_cast_exception", "reason" : "Cannot cast from [java.lang.String] to [long]." } } }, "status" : 400}
마지막 에러 메시지를 보니 대충 string을 long 타입으로, 즉 문자형을 숫자형으로 바꿀 수 없다는 뜻인 듯. String 클래스(?)는 문자형 데이터 전용인가 보다.
def 클래스는 만능
PUT iislog/_mapping{ "runtime": { "file": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = grok('.*\\/(?<file>.*)').extract(doc['url'].value).file; emit(result); } """ }, "ext": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { String result = doc['url'].value.splitOnToken('.')[-1]; emit(result); } """ }, "param_len": { "type": "long", "script": """ if (!doc['param'].empty) { def result = doc['param'].value.length(); emit(result); } """ } }}
이제 잘 됨. 코딩 알못 살려주시는 구글신
문자, 숫자형 구분 귀찮으면 그냥 def 클래스만 사용해도 된다.
PUT iislog/_mapping{ "runtime": { "file": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { def result = grok('.*\\/(?<file>.*)').extract(doc['url'].value).file; emit(result); } """ }, "ext": { "type": "keyword", "script": """ if (doc['url'].value.contains('.')) { def result = doc['url'].value.splitOnToken('.')[-1]; emit(result); } """ }, "param_len": { "type": "long", "script": """ if (!doc['param'].empty) { def result = doc['param'].value.length(); emit(result); } """ } }}
댓글 없음:
댓글 쓰기