From hibernate-commits at lists.jboss.org Mon Aug 23 13:56:46 2010
Content-Type: multipart/mixed; boundary="===============5483867822974264641=="
MIME-Version: 1.0
From: hibernate-commits at lists.jboss.org
To: hibernate-commits at lists.jboss.org
Subject: [hibernate-commits] Hibernate SVN: r20234 -
search/trunk/hibernate-search/src/main/docbook/en-US/modules.
Date: Mon, 23 Aug 2010 13:56:45 -0400
Message-ID: <201008231756.o7NHujto028493@svn01.web.mwc.hst.phx2.redhat.com>
--===============5483867822974264641==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Author: epbernard
Date: 2010-08-23 13:56:45 -0400 (Mon, 23 Aug 2010)
New Revision: 20234
Modified:
search/trunk/hibernate-search/src/main/docbook/en-US/modules/query.xml
Log:
HSEARCH-563 First shot at describing Hibernate Search query DSL
Modified: search/trunk/hibernate-search/src/main/docbook/en-US/modules/quer=
y.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- search/trunk/hibernate-search/src/main/docbook/en-US/modules/query.xml =
2010-08-23 17:55:53 UTC (rev 20233)
+++ search/trunk/hibernate-search/src/main/docbook/en-US/modules/query.xml =
2010-08-23 17:56:45 UTC (rev 20234)
@@ -42,7 +42,8 @@
=
- Creating a Lucene query
+ Creating a Lucene query either via the Hibernate Search query =
DSL
+ (recommended) or from scratch
=
@@ -70,18 +71,40 @@
FullTextSession fullTextSession =3D Search.getFullTextSession(session); =
=
- The actual search facility is built on native Lucene queries which=
the
- following example illustrates.
+ You then have two options to build the full-text query: the Hibern=
ate
+ Search query DSL or the native Lucene query.
=
+ If you use the Hibernate Search query DSL, it will look like
+ this:
+
+ final QueryBuilder b =3D fullTex=
tSession.getSearchFactory().buildQueryBuilder().forEntity( Myth.class ).get=
();
+org.apache.lucene.search.Query luceneQuery =3D
+ b.keyword()
+ .onField("history").boostedTo(3)
+ .matching("storm")
+ .createQuery();
+
+org.hibernate.Query fullTextQuery =3D fullTextSession.createFullTextQuery(=
luceneQuery );
+List result =3D fullTextQuery.list(); //return a list of managed objects =
+
+ You can alternatively write your Lucene query by hand either using=
the
+ query parser or the programmatic API. If you are considering the
+ programmatic API, we highly encourage you to use the Hibernate Search qu=
ery
+ DSL (or a mix of both).
+
- Creating a Lucene query
+ Creating a Lucene query from scratch via the query parser
=
- org.apache.lucene.queryParser.QueryParser parser =3D =
- new QueryParser("title", new StopAnalyzer() );
+ org.apache.lucene.queryParser.=
QueryParser parser =3D =
+ new QueryParser("title", fullTextSession.getSearchFactory().getAnalyze=
r(Myth.class) );
+try {
+ org.apache.lucene.search.Query luceneQuery =3D parser.parse( "history:=
storm^3" );
+}
+catch (ParseException e) {
+ //handle parsing failure
+}
=
-org.apache.lucene.search.Query luceneQuery =3D parser.parse( "summary:Fest=
ina Or brand:Seiko" );
-org.hibernate.Query fullTextQuery =3D fullTextSess=
ion.createFullTextQuery( luceneQuery );
-
+org.hibernate.Query fullTextQuery =3D fullTextSession.createFullTextQuery(=
luceneQuery );
List result =3D fullTextQuery.list(); //return a list of managed objects =
=
@@ -92,8 +115,8 @@
iterate() and scroll() methods can=
be
used.
=
- In case you are using the Java Persistence APIs of Hibernate (aka =
EJB
- 3.0 Persistence), the same extensions exist:
+ In case you are using the Java Persistence APIs of Hibernate, the =
same
+ extensions exist:
=
Creating a Search query using the JPA API
@@ -104,12 +127,14 @@
org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
=
...
-org.apache.lucene.queryParser.QueryParser parser =3D =
- new QueryParser("title", new StopAnalyzer() );
+final QueryBuilder b =3D fullTextEntityManager.getSearchFactory().buildQue=
ryBuilder().forEntity( Myth.class ).get();
+org.apache.lucene.search.Query luceneQuery =3D
+ b.keyword()
+ .onField("history").boostedTo(3)
+ .matching("storm")
+ .createQuery();
=
-org.apache.lucene.search.Query luceneQuery =3D parser.parse( "summary:Fest=
ina Or brand:Seiko" );
javax.persistence.Query fullTextQuery =3D fullText=
EntityManager.createFullTextQuery( luceneQuery );
-
List result =3D fullTextQuery.getResultList(); //return a list of managed =
objects
=
@@ -128,8 +153,13 @@
manipulation API.
=
- Building a Lucene query
+ Building a Lucene query from scratch
=
+ You have several options: use the query parser (fine for simple
+ queries) or the Lucene programmatic API (for more complex use cases).
+ Particularly if you plan on using the programmatic API, we highly
+ recommend you have a look at the Hibernate Search query DSL.
+
It is out of the scope of this documentation on how to exactly
build a Lucene query. Please refer to the online Lucene documentatio=
n or
get hold of a copy of either Lucene In Action or Hibernate Search in
@@ -137,8 +167,117 @@
=
+ Building a Lucene query with Hibernate Search query DSL
+
+ Writing full-text queries with the Lucene programmatic API is
+ quite complex. It's even more complex to understand the code once
+ written. Besides the inherent API complexity, you have to remember to
+ convert your parameters to their string equivalent as well as make s=
ure
+ to apply the correct analyzer to the right field (an ngram analyzer =
will
+ for example use several ngrams as the tokens for a given word and sh=
ould
+ be searched as such).
+
+ Hibernate Search query DSL make use of a style of API called a
+ fluent API. This is a fancy name for an API that has a few key
+ characteristics:
+
+
+
+ it has meaningful method names making a succession of
+ operations reads almost like English
+
+
+
+ it limits the options offered to what makes sense in a giv=
en
+ context (thanks to strong typing and IDE autocompletion).
+
+
+
+ It often uses the chaining method pattern
+
+
+
+ it's easy to use
+
+
+
+ it's even easier to read
+
+
+
+ Let's see how to use the API. You first need to create a query
+ builder that is attached to a given indexed entity type. This
+ QueryBuilder will know what analyzer to use a=
nd
+ what field bridge to apply. You can create several
+ QueryBuilders (one for each entity type invol=
ved
+ in the root of your query. You get the
+ QueryBuilder from the
+ SearchFactory.
+
+ QueryBuilder mythQB =3D searchFactory.buildQueryBuil=
der().forEntity( Myth.class ).get();
+
+ You can also override the analyzer used for a given field or
+ fields. This is rarely needed and should be avoided unless you know =
what
+ you are doing (like many things :)).
+
+ QueryBuilder mythQB =3D searchFactory.buildQueryBuil=
der()
+ .forEntity( Myth.class )
+ .overridesForField("history","stem_analyzer_definition");
+ .get();
+
+ From the query builder, you are then ready to... build queries.
+ What's interesting is that we build Lucene queries: you can easily m=
ix
+ and match Lucene's query parser generated Query
+ objects or a Query object you have assembled =
with
+ the Lucene programmatic API and use them with the Hibernate Search D=
SL
+ should the DSL be missing some queries.
+
+ Here is how you search for a specific word:
+
+ Query luceneQuery =3D mythQB.keyword().onField("hist=
ory").matching("storm").createQuery();
+
+ keyword() means that you are trying to
+ find a specific word. onField() tells in wh=
ich
+ lucene field to look. matching() tells what=
to
+ look for. And finally createQuery() does cr=
eate
+ the Lucene query object. A lot is going on under this line of code.
+ First the value storm is passed through the history
+ FieldBridge: it does not matter here but you =
will
+ see that it's quite handy when dealing with numbers or dates. Second=
the
+ field bridge value is then passed to the analyzer used to index
+ history.
+
+ fluent api contextual autocompletion
+
+ analyzer
+
+ query several words
+
+ ignore analyzer
+
+ field bridge (ignore)
+
+ fuzzy wildcard
+
+ range query (form to above below excludeLimit
+
+ phrase query
+
+ boolean queries (must, should must not, all, except)
+
+ multiple fields
+
+ boosted
+
+ list of options
+
+
+
Building a Hibernate Search query
=
+ Let's now see how to build the Hibernate Search query from the
+ Lucene one.
+
Generality
=
@@ -965,4 +1104,4 @@
run Lucene specific queries. Check
for more information.
-
\ No newline at end of file
+
--===============5483867822974264641==--