Hibernate and Postgres FTS
04 Feb 2015Hello! We have a Postgres database that we'd like to search over. After much debate, we decided that Postgres's full text search is good enough. Our initial thought was to use our existing ElasticSearch infrastructure and code — however as we are using Postgres — the built in searching 'comes for free'.
The above article will give you more than enough information to use Postgres FTS, what I wish to demonstrate is getting Hibernate, your friendly neighbourhood ORM, to play nicely with it.
The methodology used here was inspired/learned from this article.
So obviously Hibernate requires you to assert a dialect of SQL that is compatible with the database it must talk to. Here I am declaring it as PgFullTextDialect
, this is a custom dialect that I have defined as...
}
This is where we register additional functions on top of those defined in PostgreSQLDialect
, which doesn't contain the full text functions. If you've used PG FTS before, you'll know of ts_rank
which is used to get a relevance rank for a search result. You'll also know to_tsquery
which turns a string of text (your query) into an object Postgres can use to search.
The one you probably don't recognise is fts
, which is infact not a PG function at all but the name I have assigned to the special Postgres syntax of @@
, used to compare a text vector to a query vector. Hibernate needs to be made aware of this syntax and requires us to declare a new function type, rather than just the name and return type like we did for the previous two. This is defined as...
}
Here we have implemented the interface SQLFunction
. Like before we declare the return type of the function, we also implement two methods that indicate how Hibernate should handle the method. Crucially however we implement a method that is capable of rendering the function, that is, generating a valid SQL statement given some input. This is where the special syntax @@
is made available to Hibernate.
Finally, using the JPA CriteriaBuilder
, we can make an FTS query by asserting that the function fts
returns true given a searchString
. Note that in this example the field to be search against is hardcoded and therefore is not specified here.
Hopefully this has been helpful if you are using JPA and Hibernate with Postgres for the purposes of full text searching. Thanks for reading!
Originally posted on MetaBroadcast's blog.