Dari MySQL Ke Algolia Melalui Python
Hari ini saya harus melakukan operasi indexing di Algolia berdasarkan data dari database MySQL yang sudah ada. Saya hanya memiliki akses ke database tersebut tanpa kode program. Saya tidak menemukan tools otomatis untuk melakukan hal ini seperti layaknya Logstash di ELK (Elasticsearch, Logstash, Kibana). Beruntungnya, tidak sulit untuk menulis kode program yang membaca dari database MySQL dan mengirimkannya ke Algolia karena Algolia telah menyediakan libray pendukung di beberapa bahasa pemograman populer. Pertanyaannya adalah saya harus menulis dalam bahasa pemograman apa? Ini pastinya adalah sebuah script CLI dan bukannya aplikasi web; oleh sebab itu saya tidak akan menggunakan bahasa favorit saya: Java. Setelah berpikir sejenak, saya menyadari bahwa satu-satunya bahasa pemograman yang saya kuasai dan tepat untuk CLI adalah Python.
Sayapun segera membuat proyek baru di PyCharm. Pada konfigurasi Virtualenv proyek tersebut, saya memastikan bahwa saya menggunakan Python3. Selain itu, saya membuat file requirements.txt
dengan isi seperti berikut ini:
PyCharm dengan pintar akan menyarankan untuk men-install Python package yang dibutuhkan di file requirements.txt
. Beberapa paket yang penting yang saya pakai adalah mysql-connector-python
, algoliasearch
dan Click
. Paket mysql-connector-python
dibutuhkan untuk melakukan query ke database MySQL, sementara itu paket algoliasearch
dipakai untuk menambahkan object baru di index Algolia. Paket Click
akan membuat pemograman aplikasi CLI menjadi lebih mudah dan sebagai pemanis, paket colorama
akan memberikan warna pada tampilan CLI yang membosankan.
Setelah paket yang dibutuhkan semuanya berhasil ter-install, saya segera memilih menu Tool, Create setup.py di PyCharm. Saya pun mengisi informasi program di kotak dialog New Setup Script dan menekan tombol Ok. Hasilnya adalah sebuah file baru dengan nama setup.py
. File ini dibutuhkan untuk Distutils
yang akan mempermudah distribusi dan instalasi aplikasi Python, terutama aplikasi CLI seperti yang sedang saya buat. Karena menggunakan Click
, saya perlu melakukan sedikit perubahan pada file setup.py
yang dihasilkan PyCharm sehingga terlihat seperti berikut ini:
Bagian yang penting disini adalah entry_points
. Nilai my-migration
menunjukkan nama perintah yang nantinya akan dipakai untuk menjalankan aplikasi ini di terminal. Sementara itu, nilai migration:cli
menunjukkan bahwa kode program utama terletak di file migration.py
.
Akan tetapi, sebelum membuat file migration.py
, saya akan membuat file database.py
terlebih dahulu. Isinya terlihat seperti pada kode program berikut ini:
Pada contoh di atas, kode program query()
akan menggunakan mysql-connector-python
untuk mengerjakan sebuah query dan mengembalikan hasilnya dalam bentuk dictionary. Programmer Java akan lebih mengenal struktur data ini sebagai Map
.
Sekarang saatnya membuat file migration.py
dengan isi seperti berikut ini:
Kode program convert()
berisi pemetaan dari dictionary yang diperoleh dari database ke struktur data JSON yang akan disimpan di Algolia. Disini, saya menggunakan objectId
yang merupakan nama khusus di Algolia untuk pengenal (id) sebuah object di Algolia. Bila nilai objectId
ini sudah pernah dipakai, Algolia tidak akan membuat object baru melainkan memperbaharui object dengan objectId
yang sama tersebut.
Penggunaan decorator seperti @click.group()
dan @click.option()
merupakan fasilitas dari Click
. Decorator @cli.command()
(nilai cli
disini merujuk pada function cli()
) menunjukkan bahwa function algolia()
adalah sebuah sub command yang bisa dikerjakan dengan perintah seperti my-migration algolia
. Dengan demikian, saya bisa membuat sub command baru suatu hari nanti cukup dengan menambahkan function baru.
Click
juga menyediakan beberapa utilitas berguna seperti click.confirm()
untuk meminta konfirmasi dari pengguna dan click.progressbar()
untuk menampilkan perkembangan saat mengerjakan sesuatu yang lama.
Pada function algolia()
, saya menggunakan list comprehension untuk mempersingkat kode program. Ini adalah fitur yang unik yang hanya ada di Python. Walaupun mungkin terlihat aneh, programmer penggemar matematika akan suka dengannya! Sebagai contoh [items[i:i+chunk] for i in range(0, len(items), chunk)]
akan menciptakan sebuah list baru. Ekspresi range(0, len(items), chunk)
akan menghasilkan list dengan nilai berupa [0, chunk, chunk*2, chunk*3, ..., len(items)]
. Dengan demikian, list comprehension tersebut akan menghasilkan nilai seperti [items[0:0+chunk], items[chunk:chunk+chunk*2], items[chunk+chunk*2:chunk+chunk*2+chunk*3], ...]
. Kode program items[i:i+chunk]
akan membuat list baru berdasarkan isi list items
mulai dari elemen i
hingga sebelum elemen i+chunk
. Jadi, hasil akhir dari list comprehension ini adalah sebuah list yang mengandung list yang dibagi dengan ukuran rata sebanyak chunk
. Singkat sekali, bukan? Pada bahasa lain, ini minimal membutuhkan beberapa baris!
Bukan hanya itu, list comprehension juga dapat mengandung list comprehension lainnya (nested) seperti [[convert(i) for i in j] for j in bar]
. Yang ini menghemat dua kali for loop! Bandingkan lagi dengan list comprehension yang saya tulis di kode program saya: [[convert(i) for i in j] for j in [items[k:k+chunk] for k in range(0, len(items), chunk)]]
. Yang ini setara dengan tiga kali for loop. Luar biasa singkat, bukan?
Mengapa membagi isi tabel ke dalam chunks? Karena saya tidak ingin memanggil index.add_objects()
untuk setiap record yang ada. Akan lebih efisien bila saya mengirim banyak objects bersamaan setiap kali memanggil endpoint Algolia selama jumlah objects tersebut tidak melebihi limit yang ada.
Untuk menjalankan aplikasi CLI ini tanpa melakukan instalasi, saya bisa membuka sebuah Terminal baru di PyCharm. Setiap terminal di PyCharm sudah dilengkapi dengan aktivasi Virtualenv. Bila saya membuka terminal di sistem operasi, saya perlu memberikan perintah virtualenv venv
dan . venv/bin/activate
untuk mencapai hasil yang sama. Setelah itu, saya memberikan perintah berikut ini:
Sekarang, bila saya memberikan perintah my-migration
di terminal, saya akan menemukan hasil seperti berikut ini:
Untuk menampilkan informasi sub command algolia
, saya bisa memberikan perintah seperti berikut ini:
Untuk mengerjakan script ini dengan nilai default, saya cukup memberikan perintah seperti berikut ini: