ElasticSearch 폴더 인덱서
Windows의 폴더 내에서 검색을 수행하고 싶었지만 해당 파일을 검색하는 데 시간이 오래 걸리는 경우가 있습니까? PDF 파일이나 docx 문서가 많고 문장을 읽은 위치가 기억나지 않거나 특정 기사를 찾고 있습니까? 엔터프라이즈/비엔터프라이즈 애플리케이션을 위한 작은 검색 엔진을 구축하고 싶습니까? 위의 상황 중 하나에 해당하거나 단순히 ElasticSearch를 사용하여 폴더 및 해당 하위 폴더의 내용을 인덱싱하는 방법에 대해 궁금한 경우 이 문서가 적합합니다.
장면 설정
이 기사의 개발은 간단한 Windows 환경에서 이루어집니다. 이 기사를 작성할 당시 사용 중인 ElasticSearch 버전은 8.5.3 입니다. 이 문서의 끝에서 우리는 ElasticSearch 인스턴스 URL과 폴더 위치가 이 폴더의 콘텐츠를 해당 ELK 인스턴스로 인덱싱하는 완전히 작동하는 GUI 응용 프로그램을 만들 것입니다. 인덱스 이름은 UI에서 입력할 수 있으며 기존 이름 또는 새 이름이 될 수 있습니다.
Elastic Cluster는 평소와 같이 여러 인스턴스로 설정할 수 있습니다. 그러나 단일 컴퓨터 내에서 인스턴스를 실행하고 있으므로 단일 노드 모드에서 실행되도록 인스턴스를 구성할 수 있습니다. 이 단계에 대한 구성 세부 정보는 다음 섹션에 자세히 설명되어 있습니다.
GUI 응용 프로그램과 인덱서를 구축하기 위해 풍부한 라이브러리, 짧고 쉬운 개발로 인해 Python 을 사용하기로 결정했습니다. 250줄 미만의 코드로 docx, pdf 및 텍스트 인덱싱 기능을 갖춘 완전한 기능의 인덱서가 작성됩니다.
ElasticSearch 설정
zip elasticsearch 를 다운로드한 후 디렉터리에 압축을 풉니다. 인스턴스가 항상 로컬에서 실행되므로 첫 번째 단계는 보안을 비활성화하는 것입니다. 그러나 프로덕션 수준 원격 환경의 경우 보안을 제쳐두고 두는 것은 결코 좋은 방법이 아닙니다. 그런 다음 노드가 localhost에서 실행되고 localhost에서 단일 노드만 검색되도록 지정합니다. 포트는 변경되지 않습니다. (http의 경우 9200, tcp의 경우 9300)
yml 구성 (elasticsearch.yml) 은 아래에서 찾을 수 있습니다.
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl:
enabled: false
xpack.security.transport.ssl:
enabled: false
http.host: 0.0.0.0
network.host: 0.0.0.0
discovery.type: single-node
-Xms4g
-Xmx4g
이 기사의 목적은 elasticsearch 인스턴스를 실행하는 방법을 논의하는 것이 아니라 이를 사용하여 Python과 같은 고급 프로그래밍 언어를 사용하여 폴더 및 해당 하위 폴더를 인덱싱하는 방법이므로 "재미있는 부분"으로 이동하겠습니다.
사용자 인터페이스 디자인
elasticsearch 폴더 인덱서는 처음에는 명령줄 응용 프로그램이었지만 개발이 진행됨에 따라 간단한 GUI를 구축하기로 결정했습니다. GUI를 설정하기 위해 나는 tkinter 를 사용 했지만 다른 파이썬 GUI 라이브러리도 가능합니다.
import tkinter as tk
from PIL import ImageTk, Image
import tkinter.ttk as ttk
root= tk.Tk('Chipster')
root.title("ElasticSearch Folder Indexer ")
root.resizable(False,False)
canvas1 = tk.Canvas(root, width=400, height=600, relief='raised')
img = ImageTk.PhotoImage(Image.open("elk.png"))
img.width = 0.1
img.height = 0.1
imglabel = tk.Label(root,image=img)
canvas1.create_window(20,30,window = imglabel)
label1 = tk.Label(root, text='ElasticSearch Folder Indexer', background="lightblue")
label1.config(font=('Serif', 14, "bold"))
canvas1.create_window(230, 78, window=label1)
label2 = tk.Label(root, text='Enter the path of the folder to be indexed:')
label2.config(font=('helvetica', 10))
canvas1.create_window(200, 140, window=label2)
entry1 = tk.Entry(root , width=40)
canvas1.create_window(200, 160, window=entry1)
label3 = tk.Label(root, text='ElasticSearch Instance (ex: http://localhost:9200):')
label3.config(font=('helvetica', 10))
canvas1.create_window(200, 200, window=label3)
entry2 = tk.Entry(root,width=40)
canvas1.create_window(200, 220, window=entry2)
label4 = tk.Label(root, text='Index Name:')
label4.config(font=('helvetica', 10))
canvas1.create_window(200, 260, window=label4)
entry3 = tk.Entry(root,width=40)
canvas1.create_window(200, 280, window=entry3)
text = tk.Text(root, height=10,width=40)
progress_label = tk.Label(root,text="")
progress_label.config(font=("helvetica",12,"bold"))
client = ''
connected= False
def connect():
# Code that handles elasticsearch connection
return
def index():
# Code that handles elasticsearch indexing
return
def start_combine_in_bg():
# Threading to show real time logs in the Text Widget
style = ttk.Style()
style.theme_use('alt')
style.configure('TButton', background = 'red', foreground = 'white', width = 10, borderwidth=1, focusthickness=4, focuscolor='none' , font=('Sans serif', 12, "bold"))
style.map('TButton', background=[('active','indianred')])
button1 = ttk.Button(text='Index', command=start_combine_in_bg)
button12 = tk.Button(text='Connect' , command = connect , background="green" , foreground = 'white' ,width = 8, font=('Sans serif', 10, "bold"))
# button1.pack()
canvas1.create_window(250, 340, window=button1)
canvas1.create_window(150, 340, window=button12)
canvas1.create_window(200,370, window=progress_label)
canvas1.create_window(200,490,window=text)
canvas1.pack()
root.mainloop()
인덱스 버튼을 클릭하면 ElasticSearch 인덱싱이 시작됩니다. 그러나 콘솔에 무언가를 표시할 수 있으려면(구현의 텍스트 개체) 코드에 삽입할 실시간 텍스트를 보낼 수 있어야 합니다. GUI와 인덱싱 논리가 모두 동일한 스레드에서 실행되는 경우 GUI 처리는 전체 인덱싱 프로세스가 완료된 후에만 계속되며 전체 프로세스 중에 무엇이 잘못되었는지 궁금해하는 정지된 사용자 인터페이스에 갇히게 됩니다. 이를 방지하기 위해 백그라운드 스레드에서 인덱싱을 실행합니다. 이것이 아래에 정의된 start_combine_in_bg 함수의 목적입니다. 스레드의 대상은 실행될 호출된 함수, 즉 인덱스 함수입니다.
def start_combine_in_bg():
threading.Thread(target=index).start()
def connect():
global client
elk_url = entry2.get()
if elk_url is None or not elk_url:
client = Elasticsearch("http://localhost:9200")
else:
client = Elasticsearch(elk_url)
global connected
connected = True
text.insert(tk.END ,'Existing Indices')
indices = client.indices.get_alias()
for index in indices:
text.insert(tk.END ,'\n'+str(index))
print(indices)
return
인덱싱 로직이 수행되는 2가지 주요 기능이 있습니다. 첫 번째는 일종의 래퍼인 인덱스 기능입니다. 논리는 간단하며 아래에 나와 있습니다. 인덱스 버튼을 클릭하면 이 함수가 호출됩니다.
def index():
if connected is False:
connect()
print("INDEX Clicked")
dir_to_index = entry1.get()
if os.path.isdir(dir_to_index) is False:
all_files = get_files_in_dir('.')
else:
all_files = get_files_in_dir(dir_to_index)
text.insert(tk.END,"TEST" ) # "\n " + "TOTAL FILES:", len( all_files )
try:
resp = helpers.bulk(
client,
yield_docs( all_files,text,entry3.get() , progress_label )
)
text.insert (tk.END,"\nhelpers.bulk() RESPONSE:"+ str(resp))
text.insert (tk.END,"RESPONSE TYPE:"+ str(type(resp)))
except Exception as err:
print("\nhelpers.bulk() ERROR:", str(err))
text.see(tk.END)
return
def yield_docs(all_files, textB: tk.Text , index, label: tk.Label):
if not index or index is None or len(index) == 0:
textB.insert(tk.END ,"\nNo Index Provided")
return
count = 0
for _id, _file in enumerate(all_files):
count+=1
label.configure(text="File:"+str(count) + "/" + str(len(all_files)))
textB.insert(tk.END ,"\nIndexing : " + _file)
textB.see(tk.END)
file_name = _file[ _file.rfind(slash)+1:]
try:
if file_name.lower().endswith(('.html' , '.txt' , '.php' ,'.htm')) is True :
data = get_data_from_text_file( _file )
data = "".join( data )
doc_source = {
"file_name": file_name,
"data": data ,
"file_path":_file
}
elif file_name.lower().endswith((".docx", ".doc")) is True :
pages = getText(_file)
for page in pages:
doc_source = {
"file_name": file_name,
"data": page,
"file_path":_file
}
yield {
"_index": index,
"_source": doc_source
}
elif file_name.lower().endswith((".pdf")) is True :
print("Ends with pdf")
pages = get_text(_file)
for page in pages:
doc_source = {
"file_name": file_name,
"data": page,
"file_path":_file
}
yield {
"_index": index,
"_source": doc_source
}
else:
doc_source = {
"file_name": file_name,
"data": _file,
"file_path":_file
}
yield {
"_index": index,
"_source": doc_source
}
except Exception as err:
print('\nError ',err)
doc_source = {
"file_name": file_name,
"data": _file,
"file_path":_file
}
yield {
"_index": index,
"_source": doc_source
}
맺음말
ElasticSearch 폴더 인덱서는 개발자뿐만 아니라 다른 사람들에게도 적용 가능한 많은 사용 사례가 있습니다. 이것은 폴더 인덱싱 및 검색을 위한 완전한 기능의 플랫폼이 되도록 확장될 수 있습니다. 현재 검색 부분은 외부 응용 프로그램이나 우편 배달부를 통해 수행할 수 있습니다. 폴더의 특정 파일, 문서 내의 특정 텍스트 또는 코딩 파일 내의 특정 코드 부분을 검색하는 데 사용할 수 있습니다.
Python이 사전 설치되지 않은 Windows PC에서 실행할 수 있는 이 애플리케이션의 배포판은 dist 폴더 내의 다음 GitHub 링크에서 찾을 수 있습니다. 폴더 인덱서를 작동시키려면 ui 폴더 내에서 ui.exe를 실행하는 것으로 충분합니다.
Github:https://github.com/joanjanku2000/elk-folder-indexer/tree/latest
여기까지 오셨다면 많은 관심 부탁드립니다. 건배.
© 조안 잔쿠 2022

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































