11from elasticsearch import Elasticsearch
2- from typing import List , Dict , Any
2+ from typing import List , Dict , Any , Tuple
33from datetime import datetime
44
55
@@ -8,7 +8,7 @@ class ElasticsearchService:
88
99 def __init__ (self , host : str = "elasticsearch" , port : int = 9200 ):
1010 self .es = Elasticsearch ([{'host' : host , 'port' : port , 'scheme' : 'http' }])
11- self .index_name = "place_data_v3 "
11+ self .index_name = "place_data "
1212 self .log_index_name = "chatbot_log"
1313
1414 def is_connected (self ) -> bool :
@@ -48,6 +48,91 @@ def search_places(self, query: str, max_results: int = 23) -> List[str]:
4848 ]
4949
5050 return places
51+
52+ def search_places_chatbot (self , query : str , max_results : int = 100 ):
53+ """챗봇 장소 검색"""
54+ search_body = {
55+ "query" : {
56+ "match" : {
57+ "name" : {
58+ "query" : query ,
59+ "fuzziness" : "AUTO"
60+ }
61+ }
62+ },
63+ "sort" : [{"_score" : {"order" : "desc" }}],
64+ "size" : max_results ,
65+ "_source" : ["uuid" , "name" , "category" , "subcategory" , "gu" , "dong" , "ro" , "station" , "location" , "opentime" , "breaktime" , "closedate" , "phone" , "alias" , "address" , "content" ]
66+ }
67+
68+ response = self .es .search (index = self .index_name , body = search_body )
69+
70+ hits = response ['hits' ]['hits' ]
71+ places = [
72+ {
73+ 'uuid' : hit ['_source' ]['uuid' ],
74+ 'name' : hit ['_source' ]['name' ],
75+ 'category' : hit ['_source' ]['category' ],
76+ 'subcategory' : hit ['_source' ]['subcategory' ],
77+ 'gu' : hit ['_source' ]['gu' ],
78+ 'dong' : hit ['_source' ]['dong' ],
79+ 'ro' : hit ['_source' ]['ro' ],
80+ 'station' : hit ['_source' ]['station' ],
81+ 'location' : hit ['_source' ]['location' ],
82+ 'opentime' : hit ['_source' ]['opentime' ],
83+ 'breaktime' : hit ['_source' ]['breaktime' ],
84+ 'closedate' : hit ['_source' ]['closedate' ],
85+ 'phone' : hit ['_source' ]['phone' ],
86+ 'alias' : hit ['_source' ]['alias' ],
87+ 'address' : hit ['_source' ]['address' ],
88+ 'content' : hit ['_source' ]['content' ]
89+ }
90+ for hit in hits
91+ ]
92+ return places
93+
94+ def search_places_for_llm_tool (self , region : str , categories : List [str ]) -> Tuple [List [str ], int ]:
95+ """
96+ LLM 도구를 위한 장소 검색.
97+ 지역과 카테고리 정보를 바탕으로 장소 uuid 목록과 총 개수를 반환합니다.
98+ """
99+ query_body = {
100+ "query" : {
101+ "bool" : {
102+ "must" : [],
103+ "filter" : []
104+ }
105+ },
106+ "size" : 10000 ,
107+ "_source" : ["uuid" ],
108+ "track_total_hits" : True
109+ }
110+
111+ if region :
112+ query_body ["query" ]["bool" ]["must" ].append ({
113+ "multi_match" : {
114+ "query" : region ,
115+ "fields" : ["gu" , "dong" , "ro" , "station" , "address" ]
116+ }
117+ })
118+
119+ if categories :
120+ query_body ["query" ]["bool" ]["filter" ].append ({
121+ "bool" : {
122+ "should" : [
123+ {"terms" : {"category.keyword" : categories }},
124+ {"terms" : {"subcategory.keyword" : categories }}
125+ ],
126+ "minimum_should_match" : 1
127+ }
128+ })
129+
130+ response = self .es .search (index = self .index_name , body = query_body )
131+
132+ uuids = [hit ['_source' ]['uuid' ] for hit in response ['hits' ]['hits' ]]
133+ total = response ['hits' ]['total' ]['value' ]
134+
135+ return uuids , total
51136
52137 def create_log_index_if_not_exists (self ):
53138 """로그 인덱스가 없으면 생성"""
@@ -57,30 +142,30 @@ def create_log_index_if_not_exists(self):
57142 mapping = {
58143 "mappings" : {
59144 "properties" : {
60- "userId" : {"type" : "keyword" },
61- "question" : {"type" : "text" , "analyzer" : "nori" },
62- "answer" : {
63- "properties" : {
64- "title" : {"type" : "text" },
65- "placeList" : {
66- "properties" : {
67- "placeId" : {"type" : "keyword" },
68- "name" : {"type" : "text" , "analyzer" : "nori" },
69- "address" : {"type" : "text" , "analyzer" : "nori" },
70- "imgUrl" : {"type" : "keyword" },
71- "location" : {
72- "lat" : {"type" : "float" },
73- "lng" : {"type" : "float" }
74- }
145+ "userId" : {"type" : "keyword" },
146+ "question" : {"type" : "text" , "analyzer" : "nori" },
147+ "answer" : {
148+ "properties" : {
149+ "title" : {"type" : "text" },
150+ "placeList" : {
151+ "properties" : {
152+ "placeId" : {"type" : "keyword" },
153+ "name" : {"type" : "text" , "analyzer" : "nori" },
154+ "address" : {"type" : "text" , "analyzer" : "nori" },
155+ "imgUrl" : {"type" : "keyword" },
156+ "location" : {
157+ "lat" : {"type" : "float" },
158+ "lng" : {"type" : "float" }
75159 }
76- },
77- "detail" : { "type" : "text" , "analyzer" : "nori" }
78- }
79- },
80- "createAt" : { "type" : "date" }
81- }
160+ }
161+ },
162+ "detail" : { "type" : "text" , "analyzer" : "nori" }
163+ }
164+ },
165+ "createAt" : { "type" : "date" }
82166 }
83167 }
168+ }
84169 self .es .indices .create (index = self .log_index_name , body = mapping )
85170 print (f"로그 인덱스 '{ self .log_index_name } ' 생성 완료" )
86171 except Exception as e :
0 commit comments