Wednesday, November 25, 2009

GroovyMag Plugin Corner: Searchable

Over the next few months, I will be reprinting some of the Plugin Corners that I've written for GroovyMag. Hopefully this will give you a taste of what you can find in GroovyMag each month (and keep my blog from being so dead). Enjoy!

From November 2008 issue

One of the most powerful Grails plugins is also one of the easiest to use. The Searchable plugin brings the power of the Compass search engine into Grails in a very Groovy way. If you haven’t tried the Searchable plugin yet, it’s time to stop making excuses and stop wasting time building complex search forms for your projects. Let’s get started.

The first step to using any plugin is to install it. From the root of your Grails project execute the following command:

grails install-plugin searchable

Now the fun begins. To make a domain class searchable, just add the static searchable flag to the class. Here’s our Book class, for example:

class Book {
static Searchable = true
String title
Integer pages
Author author

String toString(){title}

We’ve already generated the scaffolding for this class, so now let’s add a search action to our BookController like this:

def search = {
def bookList =
render(view:’list’, model:[bookList:

In order to call our new search action we will need a form, so we’ll add one to the generated list view. Put the following block of code right before the opening <table> tag in list.gsp:

<div class=”nav”>

<g:form name=”search” action=’search’>


<input type=”text” name=”query” value=”${query}”/>

<input type=”submit” value=”Search”/>



Now if we run our application - with a little data thrown in via the bootstrap - we’ll get something like this:

We can now search for any string value across any of the properties of our Book instances from a single input field. We can search the String properties as well as the Integers. For example, if we had a book called “200 Reasons to Use Grails,” and we searched for the value 200, we would find
that book along with any books that had exactly 200 pages.

Although the default behavior is to search across all the properties, we can search a specific property by prefacing the search value with propertyName: (eg: author:Rocher).

I should point out that the code we have right now will blow up if the user doesn’t enter any search value before submitting the form. Don’t worry - this is easy to fix. The dynamic search method that is added to our Book class by the Searchable plugin returns an instance of the SearchResult class. This class contains a property called ‘results’, which is an ArrayList. This is why we can so easily return it in the model to our list view. So if there is no search value we can just call Book.list() and return that instead. Let’s modify our search action to look more like this:

def search = {
def bookList
if (params.query)
bookList =
bookList = Book.list()
render(view:’list’, model:[bookList:bookList])

We’re not using any additional parameters here, but the search() method takes all the same parameters that the list() method takes - which is important when it comes to sorting and pagination. In order to make pagination work with the Searchable plugin, we need to make a few simple changes. First we’ll need to pass a couple extra pieces of information to the view. The SearchResult returned by the search() method will be used to determine the total number of objects found, and the query parameter will be passed back to the view so that it can be reused when loading subsequent pages. So now our search action will look like this:

def search = {
def bookList
if (params.query){
def searchResult =
bookList = searchResult.results
bookList = Book.list()
render(view:’list’, model:[bookList:bookList, searchResult:searchResult, query:params.query])

Now we will modify list.gsp, but since we are using the same view for both the list and search actions, we will put our changes within a g:if tag. If we are viewing search results we will modify the g:paginate tag to make use of the new values we passed in on the model. Otherwise, we will use the original g:paginate tag.

<g:if test=”${searchResult}”>

  <g:paginate total=”${}” params=”[query:query]” />



  <g:paginate total=”${Book.count()}”/>


In keeping with the Grails way, the Searchable plugin gives you sensible defaults for most settings but allows for much more customization if needed. To add this, just install the SearchableConfiguration.groovy file by executing the following command:

grails install-searchable-config

You can get more details about what you can do with this file as well as excellent documentation on the Searchable plugin page at (see references). Hopefully this tutorial will give you enough to get you going. Once you get started, more questions will undoubtedly arise, so I’ve included a list of references below.

The Searchable plugin makes including powerful full text searching so easy to do that there’s really no reason to not take advantage of it. So dig in and have fun!



V said...

That's good !!!
Tks a lot!

Anonymous said...

but I have a problem with the variable searchResults! I have to declare outside the If-statement! The problem of the code is, that when I start a search in my gsp-page, the first page is OK, but all the other pages will not be displayed: the results of the other pages are identical to the first one! I used your code. Any idea? Thanks arnold