Query DSL (Domain-Specific Language)

donghwikim00·2025년 1월 24일

19_elastic_search

목록 보기
9/11
  • 엘라스틱서치(Elasticsearch)의 JSON 기반 쿼리 언어로, 복잡한 검색을 수행

기본 사용법

  • match : 텍스트와 관련성 있는 문서 검색
  • term : 정확히 일치하는 값을 검색
  • range : 숫자, 날짜, 또는 범위를 검색

Query DSL - Term Query

  • 예제 코드를 통해 이해해 보자
  • term는 정확히 일치하는 것만 나온다.
const axios = require('axios');

const url = 'http://localhost:9200/test_index2/_search';

const query = {
    query: {
        term: {
            name:'react'
        }
    }
};

axios.post(url, query)
    .then(res => {
        // console.log(res.data);
        const jsonRes = JSON.stringify(res.data, null, 2);
        console.log(jsonRes)
    })
    .catch(err =>{
        console.error(err);
    });
  • namereact와 일치하는 것만 조회
  • 하지만 조회한 결과는 다음과 같다.
$ node 12.dsl_term.js
{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.7385771,
    "hits": [
      {
        "_index": "test_index2",
        "_id": "10",
        "_score": 0.7385771,
        "_source": {
          "name": "Advanced React React React Patterns",
          "description": "Explore advanced techniques in React to build scalable and maintainable applications."
        }
      },
      {
        "_index": "test_index2",
        "_id": "15",
        "_score": 0.6802684,
        "_source": {
          "name": "Advanced React React React Patterns Patterns Patterns",
          "description": "Explore advanced techniques in React to build scalable and maintainable applications."
        }
      }
    ]
  }
}
  • 이렇게 나온 이유를 찾아보니 엘라스틱 서치에서는 기본 필드를 text 형태(["advanced", "react", "react", "react", "patterns"] )로 저장한다고 한다. 그래서 내가 react와 일치하는 값을 얻고 싶어도 같은 react라는 이름이 들어간 값이 나오는 것이다.
  • 이 문제를 해결하기 위해 위 코드를 아래와 같이 수정했다.
const axios = require('axios');

const url = 'http://localhost:9200/test_index2/_search';

const query = {
    query: {
        term: {
            "name.keyword": "react"
        }
    }
};


axios.post(url, query)
    .then(res => {
        // console.log(res.data);
        const jsonRes = JSON.stringify(res.data, null, 2);
        console.log(jsonRes)
    })
    .catch(err =>{
        console.error(err);
    });
  • query 부분을 name.keword로 변경해 아래와 같이 실행하면

  • 아래와 같이 일치하는 값이 없다고 뜨는 것을 확인할 수 있다.

Query DSL - Range Query

  • Range가 있는 데이터 추가
const axios = require('axios');

const addRangeData = async () => {
    const url = 'http://localhost:9200/test_index2/_doc';

    const data = [
        {id : 1, name : 'Product A', price : 100},
        {id : 2, name : 'Product B', price : 200},
        {id : 3, name : 'Product C', price : 300},
        {id : 4, name : 'Product D', price : 400}
    ]  

    for(let i = 0; i < data.length; i++) {
        const res = await axios.post(`${url}/${data[i].id}`, data[i]);
        console.log(res.data);
    }
}

addRangeData().catch(err => {
    console.error(err);
})
  • Range 쿼리로 데이터 조회
const axios = require('axios');

const url = 'http://localhost:9200/test_index2/_search';

const query = {
    query: {
        range: {
            price:{
                gte: 200, // greater than or equal to
                lte: 400 // less than or equal to 
            }
        }
    }
};

axios.post(url, query)
    .then(res => {
        // console.log(res.data);
        const jsonRes = JSON.stringify(res.data, null, 2);
        console.log(jsonRes)
    })
    .catch(err =>{
        console.error(err);
    });
  • 위 코드를 실행 시 price가 200 ~ 400 사이인 데이터들이 나온다.

profile
기술 블로그입니다. 여러 언어에 대한 정리, 프로젝트 설명 등을 기록합니다.

0개의 댓글