Pengindeks Folder ElasticSearch

Dec 18 2022
Pernahkah Anda ingin melakukan pencarian di dalam folder di Windows, tetapi pencarian file itu memakan waktu lama? Anda memiliki banyak file pdf atau dokumen docx dan Anda tidak ingat di mana Anda membaca kalimat atau sedang mencari artikel tertentu? Anda ingin membuat mesin pencari kecil untuk aplikasi perusahaan / non-perusahaan Anda? Jika Anda menemukan diri Anda dalam salah satu situasi di atas, atau hanya ingin tahu tentang cara menggunakan ElasticSearch untuk mengindeks konten folder dan subfoldernya, maka artikel ini cocok untuk Anda. Pengaturan adegan Pengembangan untuk artikel ini berlangsung di Lingkungan Windows yang sederhana.

Pernahkah Anda ingin melakukan pencarian di dalam folder di Windows, tetapi pencarian file itu memakan waktu lama? Anda memiliki banyak file pdf atau dokumen docx dan Anda tidak ingat di mana Anda membaca kalimat atau sedang mencari artikel tertentu? Anda ingin membuat mesin pencari kecil untuk aplikasi perusahaan / non-perusahaan Anda? Jika Anda menemukan diri Anda dalam salah satu situasi di atas, atau hanya ingin tahu tentang cara menggunakan ElasticSearch untuk mengindeks konten folder dan subfoldernya, maka artikel ini cocok untuk Anda.

Mengatur adegan

Pengembangan untuk artikel ini berlangsung di Lingkungan Windows yang sederhana. Pada saat artikel ini ditulis versi ElasticSearch yang digunakan adalah 8.5.3 . Di akhir Artikel ini kami akan membuat Aplikasi GUI yang berfungsi penuh yang memberikan URL Instans ElasticSearch dan Lokasi Folder mengindeks konten folder ini ke dalam Instans ELK tersebut. Nama indeks dapat dimasukkan dari UI dan bisa yang sudah ada atau yang baru.

Elastic Cluster dapat diatur seperti biasa dengan beberapa instance. Namun, karena kita menjalankan instance di dalam satu komputer, kita dapat mengonfigurasi instance untuk dijalankan dalam mode node tunggal. Detail konfigurasi mengenai langkah ini dirinci di bagian berikut.

Untuk membangun aplikasi GUI dan pengindeks saya telah memutuskan untuk menggunakan Python , karena perpustakaannya yang kaya, pengembangan yang singkat dan mudah. Dalam kurang dari 250 baris kode, pengindeks yang berfungsi penuh dengan docx , pdf, dan kemampuan pengindeksan teks ditulis.

Pengaturan ElasticSearch

Setelah mengunduh zip elasticsearch , saya telah mengekstraknya ke direktori. Langkah pertama adalah menonaktifkan security , karena instance akan selalu dijalankan secara lokal. Namun, untuk lingkungan terpencil tingkat produksi, tidak pernah merupakan praktik yang baik untuk mengesampingkan keamanan. Kemudian kami menentukan bahwa node harus berjalan di localhost dan hanya menemukan satu node di localhost. Port tidak diubah. (9200 untuk http , 9300 untuk tcp)

Konfigurasi yml (elasticsearch.yml) dapat ditemukan di bawah:

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

Karena tujuan artikel ini bukan membahas cara menjalankan instance elasticsearch , melainkan cara menggunakannya untuk mengindeks folder dan subfoldernya menggunakan bahasa pemrograman tingkat tinggi seperti Python , mari beralih ke " bagian yang menyenangkan "

Merancang Antarmuka Pengguna

Pengindeks folder elasticsearch, pertama kali merupakan aplikasi baris perintah, tetapi seiring perkembangan, saya memutuskan untuk membangun GUI sederhana untuknya. Untuk mengatur GUI saya telah menggunakan tkinter tetapi perpustakaan python gui lainnya akan melakukannya.

Pengindeks Folder ElasticSearch

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()

Saat tombol Indeks diklik, pengindeksan ElasticSearch dimulai. Namun, jika kita ingin dapat menampilkan sesuatu di konsol (objek teks dalam implementasi kita), kita harus dapat mengirim teks waktu nyata untuk dimasukkan ke dalam kode. Jika GUI dan logika Pengindeksan berjalan di utas yang sama, maka pemrosesan GUI hanya akan berlanjut setelah seluruh proses pengindeksan selesai dan kami akan terjebak dengan antarmuka pengguna yang membeku bertanya-tanya apa yang salah selama keseluruhan proses. Untuk menghindarinya, kami menjalankan pengindeksan di utas latar belakang. Ini adalah tujuan dari fungsi start_combine_in_bg yang didefinisikan di bawah ini. Target Thread adalah fungsi yang dipanggil untuk dieksekusi, yang merupakan fungsi indeks.

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

Ada 2 fungsi utama di mana logika pengindeksan dilakukan. Yang pertama adalah fungsi indeks, yang juga merupakan semacam pembungkus. Logikanya sangat mudah dan ditunjukkan di bawah ini. Fungsi ini akan dipanggil ketika tombol indeks diklik.

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
                }

Kata penutup

Pengindeks folder ElasticSearch memiliki banyak kasus penggunaan yang dapat diterapkan tidak hanya untuk pengembang tetapi juga orang lain. Ini dapat diperluas menjadi platform yang berfungsi penuh untuk pengindeksan dan pencarian folder. Saat ini bagian pencarian dapat dilakukan dengan aplikasi eksternal atau melalui tukang pos. Ini dapat digunakan untuk mencari file tertentu di folder , teks tertentu di dalam dokumen, atau bagian kode tertentu di dalam file pengkodean.

Distro aplikasi ini yang dapat dijalankan di PC Windows tanpa prainstal python dapat ditemukan di tautan GitHub berikut, di dalam folder dist. Agar pengindeks folder berfungsi, menjalankan ui.exe di dalam folder ui sudah cukup.

Github:https://github.com/joanjanku2000/elk-folder-indexer/tree/latest

Terima kasih atas minat Anda jika Anda berhasil sampai di sini. Bersulang.

© Joan Janku 2022