현재 기록 되어있는 로그의 형태가 워낙 다양한데 처음 데이터 삽입시 엘라스틱 서치는 기본적으로 하이픈(-) 문자는 잘라서 토큰화 시켜서 저장한다는 사실을 몰랐다.
예를 들어 "abcd1-ef2gh-ckal" 이러한 문자를 삽입하면 엘라스틱서치는 이를 자동으로
token = [ "abcd1",
"ef2gh",
"ckal"]
이렇게 저장한다는 것이다.
당연하게도 다시 검색 시 전체 스트링 매치를 통해서 검색을 하려고 해도 원하는대로 결과가 안나오는 등 문제가 발생할 수 있다.
(일반적인 텍스트 검색이라면 위 같이 토큰화 시켜서 저장하는게 유리할 수 있으나 시리얼 넘버와 같은 경우는 꽤 골치아파지겠다.)
이것 때문에 상당히 많은 시간을 삽질하는데 썼는데 찾은 해결책 몇가지는 다음과 같다.
1. 해당하는 매핑 삭제 후, 분석기 사용 안하는 매핑으로 다시 설정 [1]
2. 애초에 데이터를 넣을때 하이픈(-) 문자 삭제 후 삽입
3. Simple Query String 사용 [2]
여기서 1,2 번은 데이터를 완전히 삭제하고 다시 넣어야하는 문제가 발생한다.
가장 이상적인 방법은 1번이지 않을까 싶다. [1]
하지만 추후 다른 컬럼이 삽입될 경우에 다시 하이픈 문자가 들어갈지도 모르는데 그때마다 매핑을 설정해주면서 넣기는 왠지 귀찮지 않을까 하는 생각이 들어서 고려하지 않기로 했다.
2번이 오히려 깔끔한 솔루션이지 않을까 하는 생각도 들었는데 엘라스틱서치 만든 사람들 나름 똑똑한 사람들일텐데 토큰화 된거만 검색이 되도록 했을까? 하는 팀장님의 의문제기 때문에 안했다(!!)
다시 구글링을 열심히 해본 결과 3번 Simple Query String으로 검색을 하면 토큰화 되지 않은 전체 스트링으로 검색이 된다고 한다. [2]
이전에 쓰던 쿼리문은 아래와 같다
아래와 같이 쿼리를 했더니 뭔가 결과가 나오는거 같긴한데 원하는 결과대로 나오질 않는다.
query = json.dumps({
"filter": {
"term": {
"userUuid": "abcd1-ef2gh-ckal"
}
},
"aggregations": {
"contentId": {
"terms": {
"field": "contentId"
}
}
}
})
그래서 아래와 같이 Simple Query String을 이용해봤다.
query = json.dumps({
"query": {
"simple_query_string":{
"field":"userUuid",
"query":"abcd1-ef2gh-ckal"
}
},
"aggregations": {
"contentId": {
"terms": {
"field": "contentId",
"size": 0
}
}
}
})
원하는 결과가 나온다!
자 이렇게 했더니 이제 여러개의 조건을 만족시키는 조건 검색도 달라져야 한다 OTL
그러려면 Zero Term Phrase 매칭이라는 걸 쓰면 되는거 같다.[3]
우선 기존의 쿼리문을 보자
{
"query": {
"bool": {
"must": [
{
"match": {
"userUuid": "abcd1-ef2gh-ckal"
}
},
{
"match": {
"gameId": 1234
}
},
{
"match": {
"actionId": "TEST"
}
}
]
}
},
"from": 0,
"size": 10,
"sort": [
{
"timestamp": {
"order": "asc",
}
}
]
}
뭐 이러한 3가지 조건을 만족시키는 쿼리문이 있는데 역시나 토크나이져 때문에 작동이 되질 않는다.
{
"query": {
"bool": {
"must": [
{
"match": {
"log.userUuid":{
"query": "abcd1-ef2gh-ckal",
"operator": "and",
"zero_terms_query": "all"
}
}
},
{
"match": {
"gameId": 1234
}
},
{
"match": {
"actionId": "TEST"
}
}
]
}
},
"from": 0,
"size": 10,
"sort": [
{
"timestamp": {
"order": "asc",
}
}
]
}
뭐 이런식이다....(하)
한 가지 더 추가된게 있는데 nested object 같은 경우는 위와 같이 . 으로 구분해서 써주니까 된다. 그냥 필드명만 썼더니 안되더라는...
일단 원하는 결과들은 손에 얻었으니 이쯤에서 마치도록 하자
다른 문제가 생기면 다른 해결책을 찾으면 되겠지 ㅋㅋ
관련 없는(??) 사진 한장 투척하고 마무리
Reference
[1] https://www.elastic.co/guide/en/elasticsearch/guide/1.x/_finding_exact_values.html#_finding_exact_values - 매핑 삭제 후, 분석기 사용 안하는 매핑으로 다시 설정
[2] https://www.elastic.co/guide/en/elasticsearch/reference/2.0/query-dsl-simple-query-string-query.html - Simple Query String 사용법
[3] https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html - Zero Term Phrase 사용법
'Data Science > Elasticsearch' 카테고리의 다른 글
Elasticsearch 관련 자료 모음 (0) | 2017.08.07 |
---|---|
Logstash dumping gzipped json file (0) | 2017.07.21 |
엘라스틱서치로 분석을 해보자 - Intro (0) | 2016.08.03 |
엘라스틱 서치 활용 (0) | 2016.04.04 |