Wie frage ich Elasticsearch mit der Elastic Groovy API in Grails ab?
Es gibt verschiedene Möglichkeiten, Elasticsearch in Grails zu integrieren. Am Besten finde ich die Groovy API von Elasticsearch. Das Ganze wird über folgende Zeilen in der BuildConfig.groovy konfiguriert.
com.spatial4j und com.vividsolutions werden für die Geo Location und Search Funktionalität von Elasticsearch benötigt.
dependencies {
...
compile group: 'org.elasticsearch', name: 'elasticsearch-groovy', version: '1.5.0', classifier: 'grails'
compile group: 'com.spatial4j', name: 'spatial4j' , version : '0.4.1'
compile group: 'com.vividsolutions', name: 'jts' , version : '1.13', excludes: 'xerces'
}
Und folgendes Beispiel zeigt eine Grails Service Methode, die Elasticsearch abfrägt. Hierbei sieht man m.E. sehr schön, wie elegant man die Queries in Groovy definieren und später die Response verarbeiten kann.
package competition
import grails.transaction.Transactional
import org.elasticsearch.action.search.SearchRequestBuilder
import org.elasticsearch.action.search.SearchResponse
import org.elasticsearch.client.Client
import org.elasticsearch.client.transport.TransportClient
import org.elasticsearch.common.settings.ImmutableSettings
import org.elasticsearch.common.settings.Settings
import org.elasticsearch.common.transport.InetSocketTransportAddress
import org.elasticsearch.index.query.QueryBuilders
import org.elasticsearch.search.aggregations.AggregationBuilders
@Transactional
class ElasticGroovyClientInGrailsService {
static transactional = false
def query() {
Client client = getESClient()
SearchRequestBuilder requestBuilder = client.prepareSearch("weinsuche")
requestBuilder
.setQuery(QueryBuilders.matchAllQuery())
.addFields("shopname", "shopurl", "kategorie", "herkunftsland", "anbauregion", "weingut", "preiseinheit")
.setSize(15)
.addAggregation(AggregationBuilders.terms("Händler").field("shopurl"))
.addAggregation(AggregationBuilders.terms("Kategorie").field("kategorie_raw"))
.addAggregation(AggregationBuilders.terms("Land").field("herkunftsland_raw"))
.addAggregation(AggregationBuilders.terms("Anbauregion").field("anbauregion_raw"))
.addAggregation(AggregationBuilders.terms("Weingut").field("weingut_raw"))
.addAggregation(AggregationBuilders.range("Preis").field("preiseinheit")
.addUnboundedTo(10.0f)
.addRange(10.0f, 15.0f)
.addRange(15.0f, 20.0f)
.addRange(20.0f, 30.0f)
.addRange(30.0f, 50.0f)
.addRange(50.0f, 100.0f)
.addUnboundedFrom(100.0f)
)
SearchResponse response = requestBuilder.execute().actionGet()
printResponse(response)
client.close()
return response
}
private printResponse(SearchResponse response) {
response.getHits().getHits().each { searchHit ->
println searchHit.fields.shopname?.value
println searchHit.fields.shopurl?.value
println searchHit.fields.kategorie?.value
println searchHit.fields.herkunftsland?.value
println searchHit.fields.anbauregion?.value
println searchHit.fields.weingut?.value
println searchHit.fields.preiseinheit?.value
}
}
private getESClient() {
Client retVal
// clustername is defined in the elastic file elasticsearch.yml
Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", "---ClusterName---").build()
TransportClient transportClient = new TransportClient(settings)
retVal = transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
return retVal
}
}