Dian Aditya

Penjahit Digital.

GIS Part 2 - Pencarian Informasi Spasial Menggunakan Hibernate Search/Lucene

Berikut ini adalah posting saya yang kedua mengenai GIS, karena topik ini dibagi menjadi 4 bagian, saya sangat menyarankan anda untuk membaca secara berurutan.

Pencarian Informasi Spasial menggunakan Hibernate Search/Lucene

Pernah pakai aplikasi yang berhubungan dengan point of interest seperti foursquare atau google latitude? Ya dua aplikasi yang saya sebutkan tersebut adalah contoh implementasi dari sebuah service yang sangat berkaitan erat dengan lokasi dan koordinat. Ketika kita membuka aplikasi, melalui browser atau perangkat mobile misalnya, aplikasi akan secara otomatis membaca koordinat dimana perangkat berada melalui GPS (dengan seizin pemilik perangkat tentunya) dan kemudian menamplikan lokasi-lokasi terdekat dengan radius tertentu dari lokasi user berada.

Pada bagian ini saya akan membahas bagaimana implementasi pengolahan data spatial menggunakan Hibernate Search.Hibernate Search adalah salah satu komponen Hibernate yang mengintegrasikan kemampuan search engine dari Apache Lucence kedalam Hiberante dan JPA model. Apache Lucene adalah pustaka yang sangat powerful untuk melakukan pencarian teks bebas secara efisien, disamping itu Lucene juga mendukung spatial search yang akan saya bahas kali ini. Hibernate Search mulai mendukung spatial search sejak versi 4.2.0.Beta1, versi terupdate ketika tulisan ini dibuat adalah 4.2.0.Beta2.

Karena masih dalam versi beta, beberapa fitur masih belum dapat digunakan dengan sempurna, salah satunya adalah error untuk query sort berdasarkan jarak terdekat.

Dalam kasus kali ini saya akan menggunakan fitur spatial search untuk menampilkan objek terdekat dari suatu koordinat dalam radius tertentu (lihat ilustrasi dibawah ini). Kumpulan objek dan koordinat disimpan dalam database. Koordinat berbasis latitude (garis lintang) dan longitude (garis bujur).

Pada ilustrasi diatas titik tengah berada pada monumen nasional, lingkaran berwarna abu-abu adalah daerah dalam radius 3 KM dari titik tengah. Titik biru yang berada di dalam lingkaran adalah daerah yang terseleksi. Sedangkan titik diluarnya adalah sebaliknya.

Kode

Untuk permulaan mari membuat desain table sederhana, karena Hibernate berbasis Object Relational Mapping (ORM) untuk contoh ini saya akan membuat sebuah JPA entity untuk mewakilkan table.

1
2
3
4
5
6
7
8
9
10
11
12
@Entity
@Table
@Indexed
@Spatial(name = "location")
public class Location implements Coordinates, Serializable {
 private long id;
 private String name;
 private Double latitude;
 private Double longitude;
 ...
}

Anotasi @Indexed mengindikasikan bahwa class tersebut akan diindex oleh Lucene. Anotasi @Spatial wajib agar data dapat diquery, entity juga diharuskan untuk mengimplementasikan interface org.hibernate.search.spatial.Coordinates.

1
2
3
4
5
public interface Coordinates {
 Double getLatitude();
 Double getLongitude();
}

Selanjutnya mari membuat data awal.

ID NAME LATITUDE LONGITUDE
1 Krukut -6.1583 106.81458
2 Kampung Bali -6.18476 106.8187
3 Kebon Sirih -6.18595 106.83517
4 Senen -6.17657 106.84376
5 Gondangdia -6.19449 106.83105
6 Kemayoran -6.16684 106.84874
7 Cikini -6.19397 106.84221
8 Gunung Sahari -6.16086 106.84462
9 Cideng -6.17554 106.80891
10 Jati Pulo -6.18186 106.80307
11 Tomang -6.17307 106.79646
12 Glodok -6.14738 106.81303
13 Cempaka Baru -6.17059 106.86522

Langkah terakhir adalah membuat query untuk menampilkan lokasi dalam radius 3 KM dari titik tengah.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 *
 * @param radius
 * Radius dalam Kilometer
 * @param lat
 * Latitude
 * @param lng
 * Longitude
 * @return List Location dalam radius dari titik tengah (lat, lng)
 */
public List<location> getLocations(int radius, double lat, double lng) {
 FullTextEntityManager em = Search.getFullTextEntityManager(entityManager);
 QueryBuilder builder = em.getSearchFactory().buildQueryBuilder().forEntity(Location.class).get();
 Query query = builder.spatial().onCoordinates("location").within(radius, Unit.KM).ofLatitude(lat).andLongitude(lng).createQuery();
 FullTextQuery q = em.createFullTextQuery(query, Location.class);

 return q.getResultList();
}

Method diatas akan mencari instance (Location) yang berada di dalam radius dari latitude dan longitude yang telah dimasukkan.

Comments