Keep calm and code on
percolate 문서내 조건을 기준으로 쿼리하기 본문
아래와 같이 사용자의 조건에 따라서 광고를 내보내야 하는 경우를 가정해봅시다.
- 광고1 : 서울 or 부산
- 광고2: 대구 and 남자 and 30대
- 광고3: (30대 이하 and 여자) or (20대 이하 and 남자)
광고 도메인은 위와같이 다양한 경우의 수에 맞추어 노출될수 있는 광고를 추출하고 내보낼 수 있어야 합니다.
기존의 데이터는 단순히 고정된 값으로만 표현할 수 있으며 그렇기 때문에 위와같이 어떤 광고가 나올수 있는지를 뽑아내는건 쉽지 않은 문제입니다. 각 경우에 맞추어 필드로 조건을 만들어준다고 하더라도 3번케이스와 같이 두 조건이 결합된경우 이를 쿼리하기는 쉽지 않을것입니다.
elasticsearch에서는 문서의 쿼리를 먼저 정의하고, 쿼리시 문서를 제공하는 방식으로 필터가 가능한 percolator 쿼리를 제공하고 있습니다. 위의 경우를 직접 만들어 테스트해보도록 합시다.
PUT http://localhost:9200/percolator_sample
Content-Type: application/json
{
"mappings": {
"properties": {
"name": {"type": "text"},
"query" : {"type" : "percolator"},
"condition": {
"properties": {
"age": {"type": "integer"},
"region": {"type": "keyword"},
"gender": {"type": "keyword"}
}
}
}
}
}
"query" 필드에 "percolator" 타입을 지정하였습니다.
"condition"하위에는 "percolator" 쿼리에 필요한 조건이 들어갈 수 있는 뼈대가 됩니다.
테스트 데이터를 아래와 같이 추가하였습니다.
###
PUT http://localhost:9200/percolator_sample/_doc/1
Content-Type: application/json
{
"name" : "쿠폰1",
"query" : {
"terms" : {"condition.region" : ["서울", "부산"]}
}
}
###
PUT http://localhost:9200/percolator_sample/_doc/2
Content-Type: application/json
{
"name" : "쿠폰2",
"query" : {
"bool" : {
"filter" : [
{"term" : {"condition.region" : "대구"}},
{"range" : {"condition.age" : {"gte": 20, "lt" : 30}}},
{"term" : {"condition.gender" : "남자"}}
]
}
}
}
###
PUT http://localhost:9200/percolator_sample/_doc/3
Content-Type: application/json
{
"name" : "쿠폰3",
"query" : {
"query_string" : {
"query" : "(condition.gender:남성 AND condition.age:[0 TO 30}) OR (condition.gender:여성 AND condition.age:[0 TO 40})"
}
}
}
이제 조회쿼리를 만들어주도록 합시다.
POST http://localhost:9200/percolator_sample/_search
Content-Type: application/json
{
"query" : {
"percolate" : {
"field": "query",
"document" : {
"condition" : {
"age" : 22,
"gender" : "남성",
"region" : "서울"
}
}
}
}
}
fileld에는 어느 필드가 percolate의 대상이 되는지를 표기하며 document에는 조회대상 문서를 정의합니다.
22살 서울 남성이면 사전에 정의된 문서의 쿠폰1, 3과 매칭되는걸 예상할 수 있을것입니다.
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.1307646,
"hits": [
{
"_index": "percolator_sample",
"_type": "_doc",
"_id": "3",
"_score": 1.1307646,
"_source": {
"name": "쿠폰3",
"query": {
"query_string": {
"query": "(condition.gender:남성 AND condition.age:[0 TO 30}) OR (condition.gender:여성 AND condition.age:[0 TO 40})"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
},
{
"_index": "percolator_sample",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"name": "쿠폰1",
"query": {
"terms": {
"condition.region": [
"서울",
"부산"
]
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
앞서 설정한 쿼리에 맞추어 매칭되는 조건을 가진 두 쿠폰 문서가 결과로 나오는것을 확인할 수 있습니다.
참고사이트
Comments