[hibernate-commits] Hibernate SVN: r20234 - search/trunk/hibernate-search/src/main/docbook/en-US/modules.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Aug 23 13:56:45 EDT 2010


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/query.xml
===================================================================
--- 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 @@
     </listitem>
 
     <listitem>
-      <para>Creating a Lucene query</para>
+      <para>Creating a Lucene query either via the Hibernate Search query DSL
+      (recommended) or from scratch</para>
     </listitem>
 
     <listitem>
@@ -70,18 +71,40 @@
 FullTextSession fullTextSession = Search.getFullTextSession(session);    </programlisting>
   </example>
 
-  <para>The actual search facility is built on native Lucene queries which the
-  following example illustrates.</para>
+  <para>You then have two options to build the full-text query: the Hibernate
+  Search query DSL or the native Lucene query.</para>
 
+  <para>If you use the Hibernate Search query DSL, it will look like
+  this:</para>
+
+  <programlisting><emphasis role="bold">final QueryBuilder b = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( Myth.class ).get();
+org.apache.lucene.search.Query luceneQuery =
+    b.keyword()
+        .onField("history").boostedTo(3)
+        .matching("storm")
+        .createQuery();</emphasis>
+
+org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
+List result = fullTextQuery.list(); //return a list of managed objects    </programlisting>
+
+  <para>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 query
+  DSL (or a mix of both).</para>
+
   <example>
-    <title>Creating a Lucene query</title>
+    <title>Creating a Lucene query from scratch via the query parser</title>
 
-    <programlisting>org.apache.lucene.queryParser.QueryParser parser = 
-    new QueryParser("title", new StopAnalyzer() );
+    <programlisting><emphasis role="bold">org.apache.lucene.queryParser.QueryParser parser = 
+    new QueryParser("title", fullTextSession.getSearchFactory().getAnalyzer(Myth.class) );
+try {
+    org.apache.lucene.search.Query luceneQuery = parser.parse( "history:storm^3" );
+}
+catch (ParseException e) {
+    //handle parsing failure
+}</emphasis>
 
-org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
-<emphasis role="bold">org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
-        </emphasis>
+org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
 List result = fullTextQuery.list(); //return a list of managed objects    </programlisting>
   </example>
 
@@ -92,8 +115,8 @@
   <literal>iterate()</literal> and <literal>scroll()</literal> methods can be
   used.</para>
 
-  <para>In case you are using the Java Persistence APIs of Hibernate (aka EJB
-  3.0 Persistence), the same extensions exist:</para>
+  <para>In case you are using the Java Persistence APIs of Hibernate, the same
+  extensions exist:</para>
 
   <example>
     <title>Creating a Search query using the JPA API</title>
@@ -104,12 +127,14 @@
     org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
 
 ...
-org.apache.lucene.queryParser.QueryParser parser = 
-    new QueryParser("title", new StopAnalyzer() );
+final QueryBuilder b = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( Myth.class ).get();
+org.apache.lucene.search.Query luceneQuery =
+    b.keyword()
+        .onField("history").boostedTo(3)
+        .matching("storm")
+        .createQuery();
 
-org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
 <emphasis role="bold">javax.persistence.Query fullTextQuery = fullTextEntityManager.createFullTextQuery( luceneQuery );</emphasis>
-
 List result = fullTextQuery.getResultList(); //return a list of managed objects  </programlisting>
   </example>
 
@@ -128,8 +153,13 @@
     manipulation API.</para>
 
     <section>
-      <title>Building a Lucene query</title>
+      <title>Building a Lucene query from scratch</title>
 
+      <para>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. </para>
+
       <para>It is out of the scope of this documentation on how to exactly
       build a Lucene query. Please refer to the online Lucene documentation or
       get hold of a copy of either Lucene In Action or Hibernate Search in
@@ -137,8 +167,117 @@
     </section>
 
     <section>
+      <title>Building a Lucene query with Hibernate Search query DSL</title>
+
+      <para>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 sure
+      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 should
+      be searched as such).</para>
+
+      <para>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:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>it has meaningful method names making a succession of
+          operations reads almost like English</para>
+        </listitem>
+
+        <listitem>
+          <para>it limits the options offered to what makes sense in a given
+          context (thanks to strong typing and IDE autocompletion).</para>
+        </listitem>
+
+        <listitem>
+          <para>It often uses the chaining method pattern</para>
+        </listitem>
+
+        <listitem>
+          <para>it's easy to use</para>
+        </listitem>
+
+        <listitem>
+          <para>it's even easier to read</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>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
+      <classname>QueryBuilder</classname> will know what analyzer to use and
+      what field bridge to apply. You can create several
+      <classname>QueryBuilder</classname>s (one for each entity type involved
+      in the root of your query. You get the
+      <classname>QueryBuilder</classname> from the
+      <classname>SearchFactory</classname>.</para>
+
+      <programlisting>QueryBuilder mythQB = searchFactory.buildQueryBuilder().forEntity( Myth.class ).get();</programlisting>
+
+      <para>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 :)).</para>
+
+      <programlisting>QueryBuilder mythQB = searchFactory.buildQueryBuilder()
+    .forEntity( Myth.class )
+        .overridesForField("history","stem_analyzer_definition");
+    .get();</programlisting>
+
+      <para>From the query builder, you are then ready to... build queries.
+      What's interesting is that we build Lucene queries: you can easily mix
+      and match Lucene's query parser generated <classname>Query</classname>
+      objects or a <classname>Query</classname> object you have assembled with
+      the Lucene programmatic API and use them with the Hibernate Search DSL
+      should the DSL be missing some queries.</para>
+
+      <para>Here is how you search for a specific word:</para>
+
+      <programlisting>Query luceneQuery = mythQB.keyword().onField("history").matching("storm").createQuery();</programlisting>
+
+      <para><methodname>keyword()</methodname> means that you are trying to
+      find a specific word. <methodname>onField()</methodname> tells in which
+      lucene field to look. <methodname>matching()</methodname> tells what to
+      look for. And finally <methodname>createQuery()</methodname> does create
+      the Lucene query object. A lot is going on under this line of code.
+      First the value storm is passed through the <literal>history</literal>
+      <classname>FieldBridge</classname>: 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
+      <literal>history</literal>.</para>
+
+      <para>fluent api contextual autocompletion</para>
+
+      <para>analyzer</para>
+
+      <para>query several words</para>
+
+      <para>ignore analyzer</para>
+
+      <para>field bridge (ignore)</para>
+
+      <para>fuzzy wildcard</para>
+
+      <para>range query (form to above below excludeLimit</para>
+
+      <para>phrase query</para>
+
+      <para>boolean queries (must, should must not, all, except)</para>
+
+      <para>multiple fields</para>
+
+      <para>boosted</para>
+
+      <para>list of options</para>
+    </section>
+
+    <section>
       <title>Building a Hibernate Search query</title>
 
+      <para>Let's now see how to build the Hibernate Search query from the
+      Lucene one.</para>
+
       <section>
         <title>Generality</title>
 
@@ -965,4 +1104,4 @@
     run Lucene specific queries. Check <xref linkend="search-lucene-native" />
     for more information.</para>
   </section>
-</chapter>
\ No newline at end of file
+</chapter>



More information about the hibernate-commits mailing list