CLOUD/OpenSource

[Elasticsearch] 웹에서 검색하기 - 초성테스트

alsruds 2023. 3. 24. 04:31

◎ hanhinsam-0.1 이용

 

[ Elasticsearch 설정 ]

● Plugin 설치

# path 환경 변수 설정
/usr/share/elasticsearch/bin/elasticsearch-plugin list

# 플러그인 설치 (비공식)
/usr/share/elasticsearch/bin/elasticsearch-plugin install file://[설치된 경로]

# 재시작
systemctl restart elasticsearch

 

Postman에서 확인

》 인덱스 생성

# GET 방식으로 인덱스 생성
http://[elasticsearch ip]:9200/[index]

	# Body - raw (JSON) 내용 추가
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0,
    "index.max_ngram_diff": 10,
    "analysis": {
      "analyzer": {
        "chosung_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "hanhinsam_chosung"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword",
        "copy_to": ["name_chosung"]
      },
      "name_chosung": {
        "type": "text",
        "analyzer": "chosung_analyzer"
      }
    }
  }
}

 

데이터 저장

 

》 저장된 데이터 초성으로 검색

 

 

[ 웹에서 검색하기 ]

Chrome (html)  ↔  Django  →  Elasticsearch

 

● Django

기본 설정

# 장고 설치
pip install django

# 디렉토리 생성
django-admin startproject config . 

# 앱 추가 + settings.py
python .\manage.py startapp app01
	# config 폴더의 settings.py 에서 INSTALLED_APPS 에 app01 추가하기

# template 파일 생성 + settings.py
'DIRS': [BASE_DIR / 'templates']

 

》 Elasticsearch 설치

pip install elasticsearch

 

urls.py

from django.contrib import admin
from django.urls import path
import app01.views
urlpatterns = [
    path('keyword', app01.views.keyword),
    path('search/', app01.views.search),
]

 

views.py

from django.http import JsonResponse
from django.shortcuts import render
from elasticsearch import Elasticsearch

def search(request):
    return render(request, "search.html")

def keyword(request):
    keyword = request.GET.get('keyword')
    es = Elasticsearch([{'host': '[elasticsearch ip]', 'port': 9200, "scheme": "http"}])

    # search함수로 검색
    docs = es.search(
        index="chosung_test",
        body={
            "size": 5,
            "query": {"wildcard": {"name_chosung": "*"+keyword+"*"}}
        }
    )

    data_list = []
    for data in docs['hits']['hits']:
        data_list.append(
            data.get('_source')
        )

    return JsonResponse({"result": data_list})

 

search.html

<!DOCTYPE html>
<html><head lang="en"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>초성검색</title>
<style>
    .hide { display: none !important; }
    .rel_search {
        display:flex;
        flex-direction:column;
        justify-content : space-around;
        border: 1px solid red;
        border-radius: 12px;
    }
    .pop_rel_keywords {
        list-style: none;
        margin-right: 30%;
    }
    .pop_rel_keywords > li {
        line-height : 250%
    }
</style></head>

<body>
<input class="search_input">
<container class="rel_search hide">
    <ul class="pop_rel_keywords">
    </ul>
</container>
<script>
const ul = document.querySelector(".pop_rel_keywords");
const searchInput = document.querySelector(".search_input");
const relContainer = document.querySelector(".rel_search");
let cache = '';

const checkInput = () => {
    const beforeInput = searchInput.value;
    timer(beforeInput);
}

const timer = (beforeInput) => {
  setTimeout(() => {
    if(searchInput.value === beforeInput) {
      console.log("입력멈춤");
      loadData(searchInput.value);
      checkInput();
    } else {
      console.log("입력변함");
      checkInput();
    }

    if(searchInput.value === "") {
      relContainer.classList.add("hide");
    } else {
      relContainer.classList.remove("hide");
    }
  }, 500);
}

const loadData = (input) => {
  const url = `http://127.0.0.1:8000/keyword?keyword=${input}`;	#설정해준 이름으로 잘 써주기

  if(cache === url) return;
  else {
    cache = url;
    fetch(url)
    .then((res) => res.json())
    .then(res => fillSearch(res.result))
  }
}

const fillSearch = (suggestArr) => {
  ul.innerHTML = "";
  suggestArr.forEach((el, idx) => {
    const li = document.createElement("li");
    li.innerHTML = el.name;
    ul.appendChild(li);
  })
   const liList = document.querySelectorAll(".pop_rel_keywords li");
}
const highlightText = () => {
}
checkInput();

</script>
</body></html>

 

● 확인

python .\manage.py runserver

적용~