Notice
Recent Posts
Recent Comments
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

Keep calm and code on

percolate 문서내 조건을 기준으로 쿼리하기 본문

Elasticsearch

percolate 문서내 조건을 기준으로 쿼리하기

Sejong Park 2021. 10. 11. 15:11

아래와 같이 사용자의 조건에 따라서 광고를 내보내야 하는 경우를 가정해봅시다.

  • 광고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