My Grails app is using the searchable plugin, which builds on Compass and Lucene to provide search functionality. I have two searchable classes, say Author and Book. I have mapped these classes to the search index, so that only certain fields can be searched.
To perform a search across both classes I simply call
def results = searchableService.search(query)
One of the nice features of doing the search across both class simultaneously, is that the results
object includes metadata about number of results included, number of results available, pagination details etc.
I recently added a boolean approved
flag to the Book class and I never want unapproved books to appear in the search results. One option is to replace the call above with:
def bookResults = Book.search(query + " approved:1")
def authorResults = Author.search(query)
However, I now need to figure out how to combine the metadata for both results, which is likely to be tricky (particularly pagination).
Is there a way to search across Book and Author with a single query, but only return approved books?
I've created a test app and came to the following solution. maybe it helps...
if the property
approved
only has the states0
and1
, the following query will work:I guess this can be reformulated in a better way if you don't use the QueryParser but the BooleanQueryBuilder.
BTW: if you add a method like
and
To your domains, you can even configure your search to do it like this
Do you want to be able to find authors or do you want to find books with a given author?
If you want to find books with a given author, you can configure your domain classes in the following way:
this will result in excluding the Author from the
searchableService.search(query)
-result and you'll find field names like$/Book/Author/name
in your index. (use luke to examine your index: http://code.google.com/p/luke/).You can change the name of those fields by configuring a better
prefix
in your Book-class:this will change the name of the field in the index to
bookauthor
.If you now search with
searchableService.search(query)
, you'll find all books where the name of the book or the name of the author contains the search term. You can even restrict the search to a given author by using theauthorname:xyz
syntax.If you really would like to mix the search results, I only know the solution you already mentioned: mixing both results with your own code, but I guess it will be hard to mix the scoring of the hits in a good way.
Update to your response: Here's my pagination code...
.gsp:
controller:
So if you just merge the results of your two searches and add the
result.total
s, this could work for you.