[hibernate-commits] Hibernate SVN: r11600 - in trunk/HibernateExt/search: doc/reference/en/modules and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed May 30 22:48:09 EDT 2007


Author: epbernard
Date: 2007-05-30 22:48:08 -0400 (Wed, 30 May 2007)
New Revision: 11600

Modified:
   trunk/HibernateExt/search/doc/reference/en/master.xml
   trunk/HibernateExt/search/doc/reference/en/modules/architecture.xml
   trunk/HibernateExt/search/doc/reference/en/modules/configuration.xml
   trunk/HibernateExt/search/doc/reference/en/modules/mapping.xml
   trunk/HibernateExt/search/doc/reference/en/modules/query.xml
   trunk/HibernateExt/search/src/java/org/hibernate/search/reader/ReaderProvider.java
Log:
HSEARCH-39
HSEARCH-38
Update search documentation

Modified: trunk/HibernateExt/search/doc/reference/en/master.xml
===================================================================
--- trunk/HibernateExt/search/doc/reference/en/master.xml	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/doc/reference/en/master.xml	2007-05-31 02:48:08 UTC (rev 11600)
@@ -1,25 +1,25 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
-        "../../../../../Hibernate3/doc/reference/support/docbook-dtd/docbookx.dtd" [
-        <!ENTITY architecture SYSTEM "modules/architecture.xml">
-        <!ENTITY configuration SYSTEM "modules/configuration.xml">
-        <!ENTITY mapping SYSTEM "modules/mapping.xml">
-        <!ENTITY query SYSTEM "modules/query.xml">
-        <!ENTITY batchindex SYSTEM "modules/batchindex.xml">
-        ]>
+"../../../../../Hibernate3/doc/reference/support/docbook-dtd/docbookx.dtd" [
+<!ENTITY architecture SYSTEM "modules/architecture.xml">
+<!ENTITY configuration SYSTEM "modules/configuration.xml">
+<!ENTITY mapping SYSTEM "modules/mapping.xml">
+<!ENTITY query SYSTEM "modules/query.xml">
+<!ENTITY batchindex SYSTEM "modules/batchindex.xml">
+]>
 <book lang="en">
   <bookinfo>
     <title>Hibernate Search</title>
-    <subtitle>Apache <trademark>Lucene</trademark>
-  Integration</subtitle>
 
+    <subtitle>Apache <trademark>Lucene</trademark> Integration</subtitle>
+
     <subtitle>Reference Guide</subtitle>
 
-    <releaseinfo>3.0.0.Beta1</releaseinfo>
+    <releaseinfo>3.0.0.Beta2</releaseinfo>
 
     <mediaobject>
       <imageobject>
-        <imagedata fileref="images/hibernate_logo_a.png" format="png"/>
+        <imagedata fileref="images/hibernate_logo_a.png" format="png" />
       </imageobject>
     </mediaobject>
   </bookinfo>
@@ -29,29 +29,29 @@
   <preface id="preface" revision="2">
     <title>Preface</title>
 
-    <para>Full text search engines like <productname>Apache Lucene</productname>
-        are a very powerful technology to
-bring free text/efficient queries to applications. If suffers several mismatches
-when dealing with a object domain model (keeping the index up to date, mismatch
-between the index structure and the domain model, querying mismatch...)
-Hibernate Search indexes your domain model thanks to a few annotations, takes
-care of the database / index synchronization and brings you back regular managed
-objects from free text queries.
-Hibernate Search is using <ulink url="http://lucene.apache.org">Apache Lucene</ulink>
-under the cover.</para>
+    <para>Full text search engines like <productname>Apache
+    Lucene</productname> are a very powerful technology to bring free
+    text/efficient queries to applications. If suffers several mismatches when
+    dealing with a object domain model (keeping the index up to date, mismatch
+    between the index structure and the domain model, querying mismatch...)
+    Hibernate Search indexes your domain model thanks to a few annotations,
+    takes care of the database / index synchronization and brings you back
+    regular managed objects from free text queries. Hibernate Search is using
+    <ulink url="http://lucene.apache.org">Apache Lucene</ulink> under the
+    cover.</para>
 
-  <para>Hibernate Search is a work in progress and new features are cooking in
-  this area. So expect some compatibility changes in subsequent
-  versions.</para>
+    <para>Hibernate Search is a work in progress and new features are cooking
+    in this area. So expect some compatibility changes in subsequent
+    versions.</para>
   </preface>
 
-    &architecture;
+  &architecture;
 
-    &configuration;
+  &configuration;
 
-    &mapping;
+  &mapping;
 
-    &query;
+  &query;
 
-    &batchindex;
+  &batchindex;
 </book>
\ No newline at end of file

Modified: trunk/HibernateExt/search/doc/reference/en/modules/architecture.xml
===================================================================
--- trunk/HibernateExt/search/doc/reference/en/modules/architecture.xml	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/doc/reference/en/modules/architecture.xml	2007-05-31 02:48:08 UTC (rev 11600)
@@ -6,31 +6,29 @@
   engine. Both are backed by Apache Lucene.</para>
 
   <para>When an entity is inserted, updated or removed to/from the database,
-  Hibernate Search keeps track of this event
-  (through the Hibernate event system) and schedule an index update. All the
-  index updates are handled for you without you having to use the Apache
-  Lucene APIs.</para>
+  Hibernate Search keeps track of this event (through the Hibernate event
+  system) and schedule an index update. All the index updates are handled for
+  you without you having to use the Apache Lucene APIs.</para>
 
   <para>To interact with Apache Lucene indexes, Hibernate Search has the
   notion of <classname>DirectoryProvider</classname> . A directory provider
   will manage a given Lucene <classname>Directory</classname> type. You can
   configure directory providers to adjust the directory target.</para>
 
-  <para>Hibernate Search can also use a Lucene
-  index to search an entity and return a (list of) managed entity saving you
-  from the tedious Object / Lucene Document mapping and low level Lucene APIs.
-  The same persistence context is shared between Hibernate and Hibernate
-  Search ; as a matter of fact, the Seearch Session is built on top of the
-  Hibernate Session. The application code use the unified
-  <classname>org.hibernate.Query</classname> API exactly the way a HQL or
-  native query would be done.</para>
+  <para>Hibernate Search can also use a Lucene index to search an entity and
+  return a (list of) managed entity saving you from the tedious Object /
+  Lucene Document mapping and low level Lucene APIs. The same persistence
+  context is shared between Hibernate and Hibernate Search ; as a matter of
+  fact, the Search Session is built on top of the Hibernate Session. The
+  application code use the unified <classname>org.hibernate.Query</classname>
+  API exactly the way a HQL or native query would be done.</para>
 
   <section>
     <title>Batching Scope</title>
 
-    <para>To be more efficient, Hibernate Search batch the interactions with
-    the Lucene index. There is currently two types of batching depending on
-    the expected scope.</para>
+    <para>To be more efficient, Hibernate Search batch the write interactions
+    with the Lucene index. There is currently two types of batching depending
+    on the expected scope.</para>
 
     <para>When out of transaction, the index update operation is executed
     right after the actual database operation. This scope is really a no
@@ -55,9 +53,9 @@
         the transaction is committed.</para>
 
         <note>
-          <para>Disclamer, the work in not ACID in the strict sense of it, but
-          ACID behavior is rarely useful for full text search indexes since
-          they can be rebuilt from the source at any time.</para>
+          <para>Disclaimer, the work in not ACID in the strict sense of it,
+          but ACID behavior is rarely useful for full text search indexes
+          since they can be rebuilt from the source at any time.</para>
         </note>
       </listitem>
     </itemizedlist>
@@ -80,7 +78,7 @@
 
     <para>Hibernate Search offers the ability to let the scoped work being
     processed by different back ends. Two back ends are provided out of the
-    box for 2 different scenarii.</para>
+    box for 2 different scenarios.</para>
 
     <section>
       <title>Lucene</title>
@@ -146,8 +144,8 @@
       <title>Custom</title>
 
       <para>Hibernate Search is an extensible architecture. While not yet part
-      of the public API, pluging a third party back end is possible. Feel free
-      to drop ideas to
+      of the public API, plugging a third party back end is possible. Feel
+      free to drop ideas to
       <literal>hibernate-dev at lists.jboss.org</literal>.</para>
     </section>
   </section>
@@ -185,4 +183,44 @@
       completely unrealistic way).</para>
     </section>
   </section>
+
+  <section id="search-architecture-readerstrategy" xreflabel="Reader strategy">
+    <title>Reader strategy</title>
+
+    <para>When executing a query, Hibernate Search interacts with the Apache
+    Lucene indexes through a reader strategy.</para>
+
+    <section>
+      <title>not-shared</title>
+
+      <para>Every time a query is executed, a Lucene IndexReader is opened.
+      This strategy is not the most efficient, opening and warming up an
+      IndexReader can be a relatively expensive operation. This strategy is
+      the default, but will be changed in the future.</para>
+    </section>
+
+    <section>
+      <title>shared</title>
+
+      <para>Hibernate Search will share the same IndexReader for a given index
+      provided that the IndexReader is still up-to-date. Generally speaking,
+      this strategy provides much better performance than the previous one. It
+      is especially true if the number of updates is much lower than the
+      read.</para>
+    </section>
+
+    <section>
+      <title>custom</title>
+
+      <para>You can write your own reader strategy that suits your application
+      needs by implementing
+      <classname>org.hibernate.search.reader.ReaderProvider</classname>. The
+      implementation must be thread safe.</para>
+
+      <note>
+        <para>Some additional strategies are planned in future versions of
+        Hibernate Search</para>
+      </note>
+    </section>
+  </section>
 </chapter>
\ No newline at end of file

Modified: trunk/HibernateExt/search/doc/reference/en/modules/configuration.xml
===================================================================
--- trunk/HibernateExt/search/doc/reference/en/modules/configuration.xml	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/doc/reference/en/modules/configuration.xml	2007-05-31 02:48:08 UTC (rev 11600)
@@ -351,6 +351,26 @@
     </section>
   </section>
 
+  <section>
+    <title>Reader strategy configuration</title>
+
+    <para>The different reader strategies are described in <xref
+    linkend="search-architecture-readerstrategy" /> .The default reader
+    strategy is <literal>not-shared</literal>. This can be adjusted:</para>
+
+    <programlisting>hibernate.search.reader.strategy = shared</programlisting>
+
+    <para>Adding this property switch to the <literal>shared</literal>
+    strategy.</para>
+
+    <para>Or if you have a custom reader strategy:</para>
+
+    <programlisting>hibernate.search.reader.strategy = my.corp.myapp.CustomReaderProvider</programlisting>
+
+    <para>where <classname>my.corp.myapp.CustomReaderProvider</classname> is
+    the custom strategy implementation</para>
+  </section>
+
   <section id="search-configuration-event" revision="2">
     <title>Enabling automatic indexing</title>
 
@@ -367,18 +387,20 @@
     configuration is not useful with Hibernate Annotations or Hibernate
     EntityManager.</para>
 
-    <programlisting>&lt;session-factory&gt;
-    ...
-    &lt;event type="post-update"
-        &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
-    &lt;/event&gt;
-    &lt;event type="post-insert"
-        &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
-    &lt;/event&gt;
-    &lt;event type="post-delete"
-        &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
-    &lt;/event&gt;
-&lt;/session-factory&gt;</programlisting>
+    <programlisting>&lt;hibernate-configuration&gt;
+     &lt;session-factory&gt;
+        ...
+        &lt;event type="post-update"
+            &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
+        &lt;/event&gt;
+        &lt;event type="post-insert"
+            &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
+        &lt;/event&gt;
+        &lt;event type="post-delete"
+            &lt;listener class="org.hibernate.search.event.FullTextIndexEventListener"/&gt;
+        &lt;/event&gt;
+    &lt;/session-factory&gt;
+&lt;/hibernate-configuration&gt;</programlisting>
 
     <para>Be sure to add the appropriate jar files in your classpath. Check
     <literal>lib/README.TXT</literal> for the list of third party libraries. A

Modified: trunk/HibernateExt/search/doc/reference/en/modules/mapping.xml
===================================================================
--- trunk/HibernateExt/search/doc/reference/en/modules/mapping.xml	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/doc/reference/en/modules/mapping.xml	2007-05-31 02:48:08 UTC (rev 11600)
@@ -49,13 +49,14 @@
         <listitem>
           <para><literal>store</literal> : describe whether or not the
           property is stored in the Lucene index. You can store the value
-          <literal>Store.YES</literal> (comsuming more space in the index),
-          store it in a compressed way <literal>Store.COMPRESS</literal> (this
-          does consume more CPU), or avoid any storage
-          <literal>Store.NO</literal> (this is the default value). When a
-          property is stored, you can retrieve it from the Lucene Document
-          (note that this is not related to whether the element is indexed or
-          not).</para>
+          <literal>Store.YES</literal> (comsuming more space in the index but
+          allowing projection, see <xref linkend="search-query" /> for more
+          information), store it in a compressed way
+          <literal>Store.COMPRESS</literal> (this does consume more CPU), or
+          avoid any storage <literal>Store.NO</literal> (this is the default
+          value). When a property is stored, you can retrieve it from the
+          Lucene Document (note that this is not related to whether the
+          element is indexed or not).</para>
         </listitem>
 
         <listitem>
@@ -74,18 +75,22 @@
       annotation.</para>
 
       <para>Whether or not you want to store the data depends on how you wish
-      to use the index query result. As of today, for a pure
-      Hibernate Search usage, storing is not
-      necessary. Whether or not you want to tokenize a property or not depends
-      on whether you wish to search the element as is, or only normalized part
-      of it. It make sense to tokenize a text field, but it does not to do it
-      for a date field (or an id field).</para>
+      to use the index query result. For a regular Hibernate Search usage,
+      storing is not necessary. However you might want to store some fields to
+      subsequently project them (see <xref linkend="search-query" /> for more
+      information). </para>
 
+      <para>Whether or not you want to tokenize a property depends on whether
+      you wish to search the element as is, or by the words it contains. It
+      make sense to tokenize a text field, but it does not to do it for a date
+      field (or an id field). Note that fields used for sorting must not be
+      tokenized.</para>
+
       <para>Finally, the id property of an entity is a special property used
-      by Hibernate Search to ensure index unicity
-      of a given entity. By design, an id has to be stored and must not be
-      tokenized. To mark a property as index id, use the
-      <literal>@DocumentId</literal> annotation.</para>
+      by Hibernate Search to ensure index unicity of a given entity. By
+      design, an id has to be stored and must not be tokenized. To mark a
+      property as index id, use the <literal>@DocumentId</literal>
+      annotation.</para>
 
       <programlisting>@Entity
 @Indexed(index="indexes/essays")
@@ -153,6 +158,58 @@
     @Field(index=Index.TOKENIZED)
     private String city;
 
+    <emphasis role="bold">@ContainedIn</emphasis>
+    @OneToMany(mappedBy="address")
+    private Set&lt;Place&gt; places;
+    ...
+}</programlisting>
+
+      <para>In this example, the place fields will be indexed in the
+      <literal>Place</literal> index. The <literal>Place</literal> index
+      documents will also contain the fields <literal>address.id</literal>,
+      <literal>address.street</literal>, and <literal>address.city</literal>
+      which you will be able to query from. This is done thanks to the
+      <literal>@IndexedEmbedded</literal> annotation.</para>
+
+      <para><literal>@ContainedIn</literal> is useful on embedded objects that
+      are also entities (like <literal>Address</literal> in the example): it
+      basically means that when an address entity is updated, the index
+      document of the associated <literal>Place</literal>(s), also have to be
+      updated.</para>
+
+      <para>Let's make our example a bit more complex:</para>
+
+      <programlisting>@Entity
+ at Indexed
+public class Place {
+    @Id
+    @GeneratedValue
+    @DocumentId
+    private Long id;
+
+    @Field( index = Index.TOKENIZED )
+    private String name;
+
+    @OneToOne( cascade = { CascadeType.PERSIST, CascadeType.REMOVE } )
+    <emphasis role="bold">@IndexedEmbedded</emphasis>
+    private Address address;
+    ....
+}
+
+ at Entity
+ at Indexed
+public class Address {
+    @Id
+    @GeneratedValue
+    @DocumentId
+    private Long id;
+
+    @Field(index=Index.TOKENIZED)
+    private String street;
+
+    @Field(index=Index.TOKENIZED)
+    private String city;
+
     <emphasis role="bold">@IndexedEmbedded(depth = 1, prefix = "ownedBy_")</emphasis>
     private Owner ownedBy;
 
@@ -199,10 +256,11 @@
 
       <para>The default prefix is <literal>propertyName.</literal>, following
       the traditional object navigation convention. You can override it using
-      the <literal>prefix</literal> attribute.</para>
+      the <literal>prefix</literal> attribute as it is shown on the
+      <literal>ownedBy</literal> property.</para>
 
       <para><literal>depth</literal> is necessary when the object graph
-      contains a cyclic dependency of classes (not instance). For example, if
+      contains a cyclic dependency of classes (not instances). For example, if
       <classname>Owner</classname> points to <classname>Place</classname>.
       Hibernate Search will stop including Indexed embedded atttributes after
       reaching the expected depth (or is the object graph boundaries are
@@ -211,8 +269,9 @@
       1, any <literal>@IndexedEmbedded</literal> attribute in Owner (if any)
       will be ignored.</para>
 
-      <para>Such a mapping is very useful to express queries refering to
-      associated objects, such as:</para>
+      <para>Such a feature (<literal>@IndexedEmbedded</literal>) is very
+      useful to express queries refering to associated objects, such
+      as:</para>
 
       <itemizedlist>
         <listitem>
@@ -249,6 +308,15 @@
       associated entity is updated (in ou example, a <literal>Place</literal>
       index document has to be updated when the associated
       <classname>Address</classname> instance is updated.</para>
+
+      <note>
+        <para><literal>@IndexedEmbedded</literal> is supported on collections
+        too (ie to index associated object included in collections). But the
+        support is only partially implemented. It will depend on how you
+        update collections (Check HSEARCH-56 in JIRA for more informations).
+        The workaround is to manually index the object
+        (session.index())</para>
+      </note>
     </section>
 
     <section>
@@ -302,10 +370,9 @@
 
     <para>All field of a full text index in Lucene have to be represented as
     Strings. Ones Java properties have to be indexed in a String form. For
-    most of your properties, Hibernate Search does
-    the translation job for you thanks to a built-in set of bridges. In some
-    cases, though you need a fine grain control over the translation
-    process.</para>
+    most of your properties, Hibernate Search does the translation job for you
+    thanks to a built-in set of bridges. In some cases, though you need a fine
+    grain control over the translation process.</para>
 
     <section>
       <title>Built-in bridges</title>

Modified: trunk/HibernateExt/search/doc/reference/en/modules/query.xml
===================================================================
--- trunk/HibernateExt/search/doc/reference/en/modules/query.xml	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/doc/reference/en/modules/query.xml	2007-05-31 02:48:08 UTC (rev 11600)
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<chapter id="search-query">
+<chapter id="search-query" xreflabel="Querying">
   <title>Querying</title>
 
   <para>The second most important capability of <productname>Hibernate Search
   </productname> is the ability to execute a Lucene query and retrieve
   entities managed by an Hibernate session, providing the power of Lucene
-  without living the Hibernate paradygm, and giving another dimension to the
+  without living the Hibernate paradigm, and giving another dimension to the
   Hibernate classic search mechanisms (HQL, Criteria query, native SQL
   query).</para>
 
   <para>To access the <productname>Hibernate Search</productname> querying
   facilities, you have to use an Hibernate
-  <classname>FullTextSession</classname> . A SearchSession wrap an regular
+  <classname>FullTextSession</classname> . A Search Session wrap an regular
   <classname>org.hibernate.Session</classname> to provide query and indexing
   capabilities.</para>
 
@@ -30,33 +30,257 @@
 List result = fullTextQuery.list(); //return a list of managed objects    </programlisting>
 
   <para>The Hibernate query built on top of the Lucene query is a regular
-  <literal>org.hibernate.Query</literal> , you are is the same paradygm as the
+  <literal>org.hibernate.Query</literal> , you are is the same paradigm as the
   other Hibernate query facilities (HQL, Native or Criteria). The regular
   <literal>list()</literal> , <literal>uniqueResult()</literal> ,
   <literal>iterate()</literal> and <literal>scroll()</literal> can be
   used.</para>
 
-  <para>If you expect a reasonnable result number and expect to work on all of
-  them, <methodname>list()</methodname> or
-  <methodname>uniqueResult()</methodname> are recommanded.
-  <methodname>list()</methodname> work best if the entity
-  <literal>batch-size</literal> is set up properly. Note that Hibernate Seach
-  has to process all Lucene Hits elements when using
-  <methodname>list()</methodname> , <methodname>uniqueResult()</methodname>
-  and <methodname>iterate()</methodname> . If you wish to minimize Lucene
-  document loading, <methodname>scroll()</methodname> is more appropriate,
-  Don't forget to close the <classname>ScrollableResults</classname> object
-  when you're done, since it keeps Lucene resources.</para>
+  <section>
+    <title>Building queries</title>
 
-  <para>An efficient way to work with queries is to use pagination. The
-  pagination API is exactly the one available in
-  <classname>org.hibernate.Query</classname> :</para>
+    <para>Hibernate Search queries are built on top of a Lucene query. It
+    gives you a total freedom on the kind of Lucene queries you are willing to
+    execute. However, once built, Hibernate Search abstract the query
+    processing from your application using org.hibernate.Query as your primary
+    query manipulation API.</para>
 
-  <programlisting><emphasis role="bold">org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
-        </emphasis>
-fullTextQuery.setFirstResult(30);
-fullTextQuery.setMaxResult(20);
-fullTextQuery.list(); //will return a list of 20 elements starting from the 30th    </programlisting>
+    <section>
+      <title>Building a Lucene query</title>
 
-  <para>Only the relevant Lucene Documents are accessed.</para>
+      <para>This subject is generally speaking out of the scope of this
+      documentation. Please refer to the Lucene documentation or Lucene In
+      Action.</para>
+    </section>
+
+    <section>
+      <title>Building an Hibernate Search query</title>
+
+      <section>
+        <title>Generality</title>
+
+        <para>Once the Lucene query is built, it needs to be wrapped into an
+        Hibernate Query.</para>
+
+        <programlisting>FullTextSession fullTextSession = Search.createFullTextSession( session );
+org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );</programlisting>
+
+        <para>If not specified, the query will be applied on all indexed,
+        potentially returning all types of indexed classes. It is advised, for
+        a performance point of view to restrict the returned types:</para>
+
+        <programlisting>org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class );
+//or
+fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Item.class, Actor.class );</programlisting>
+
+        <para>The first example returns only matching customers, the second
+        returns matching actors and items.</para>
+      </section>
+
+      <section>
+        <title>Pagination</title>
+
+        <para>It is recommended to restrict the number of returned objects per
+        query. It is a very common use case as well, the user usually navigate
+        from one page to an other. The way to define pagination is exactly the
+        way you would define pagination in a plain HQL or Criteria
+        query.</para>
+
+        <programlisting>org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class );
+fullTextQuery.setFirstResult(15); //start from the 15th element
+fullTextQuery.setMaxResults(10); //return 10 elements</programlisting>
+
+        <note>
+          <para>It is still possible to get the total number of matching
+          elements regardless of the pagination. See
+          <methodname>getResultSize()</methodname> below</para>
+        </note>
+      </section>
+
+      <section>
+        <title>Sorting</title>
+
+        <para>Apache Lucene provides a very flexible and powerful way to sort
+        results. While the default sorting (by relevance) is appropriate most
+        of the time, it can interesting to sort by one or several
+        properties.</para>
+
+        <para>Inject the Lucene Sort object to apply a Lucene sorting strategy
+        to an Hibernate Search.</para>
+
+        <programlisting>org.hibernate.search.FullTextQuery query = s.createFullTextQuery( query, Book.class );
+org.apache.lucene.search.Sort sort = new Sort(new SortField("title"));
+<emphasis role="bold">query.setSort(sort);</emphasis>
+List results = query.list();</programlisting>
+
+        <para>One can notice the <classname>FullTextQuery</classname>
+        interface which is a sub interface of
+        <classname>org.hibernate.Query</classname>.</para>
+
+        <para>Fields used for sorting ust not be tokenized.</para>
+      </section>
+
+      <section>
+        <title>Fetching strategy</title>
+
+        <para>When you restrict the return types to one class, Hibernate
+        Search load the objects and respect the static fetching strategy
+        defined in your domain model using a single query.</para>
+
+        <para>It is often useful, however, to refine the fetching strategy for
+        a specific use case.</para>
+
+        <programlisting>Criteria criteria = s.createCriteria( Book.class ).setFetchMode( "authors", FetchMode.JOIN );
+s.createFullTextQuery( luceneQuery ).setCriteriaQuery( criteria );</programlisting>
+
+        <para>In this example, the query will return all Books matching the
+        luceneQuery. The authors collection will be loaded from the same query
+        using an SQL outer join.</para>
+
+        <para>When defining a criteria query, it is not needed to restrict the
+        entity types returned while creating the Hibernate Search query from
+        the full text session: the type is guessed from the criteria query
+        itself.</para>
+
+        <para>One cannot use <methodname>setCriteriaQuery</methodname> if more
+        than one entity type is expected to be returned.</para>
+      </section>
+
+      <section>
+        <title>Projection</title>
+
+        <para>For some use cases, returning the domain object (graph) is
+        overkill. Only a small subset of the properties is necessary.
+        Hibernate Search allows you to return only some properties:</para>
+
+        <programlisting>org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
+query.<emphasis role="bold">setIndexProjection( "id", "summary", "body", "mainAuthor.name" )</emphasis>;
+List results = query.list();
+Object[] firstResult = (Object[]) results.get(0);
+Integer id = firstResult[0];
+String summary = firstResult[1];
+String body = firstResult[2];
+String authorName = firstResult[3];</programlisting>
+
+        <para>Hibernate Search extracts the properties from the Lucene index
+        and convert them back to their object representation, returning a list
+        of <classname>Object[]</classname>. Projections avoid a potential
+        database round trip (useful if the query response time is critical),
+        but has some constraints:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>the properties projected must be stored in the index
+            (<literal>@Field(store=Store.YES)</literal>), which increase the
+            index size</para>
+          </listitem>
+
+          <listitem>
+            <para>the properties projected must use a
+            <literal>FieldBridge</literal> implementing
+            <classname>org.hibernate.search.bridge.TwoWayFieldBridge</classname>
+            or
+            <literal>org.hibernate.search.bridge.TwoWayStringBridge</literal>,
+            the latter being the simpler version</para>
+          </listitem>
+        </itemizedlist>
+
+        <para></para>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>Retrieving the results</title>
+
+    <para>Once the Hibernate Search query is built, executing it is in no way
+    different than executing a HQL or Criteria query. The same paradigm and
+    object semantic apply. All the common operations are available:
+    <methodname>list()</methodname>, <methodname>uniqueResult()</methodname>,
+    <methodname>iterate()</methodname>,
+    <methodname>scroll()</methodname>.</para>
+
+    <section>
+      <title>Performance considerations</title>
+
+      <para>If you expect a reasonable result number (for example using
+      pagination) and expect to work on all of them,
+      <methodname>list()</methodname> or
+      <methodname>uniqueResult()</methodname> are recommended.
+      <methodname>list()</methodname> work best if the entity
+      <literal>batch-size</literal> is set up properly. Note that Hibernate
+      Search has to process all Lucene Hits elements (within the pagination)
+      when using <methodname>list()</methodname> ,
+      <methodname>uniqueResult()</methodname> and
+      <methodname>iterate()</methodname>. If you wish to minimize Lucene
+      document loading, <methodname>scroll()</methodname> is more appropriate,
+      Don't forget to close the <classname>ScrollableResults</classname>
+      object when you're done, since it keeps Lucene resources. Pagination is
+      a preferred method over scrolling though.</para>
+    </section>
+
+    <section>
+      <title>Result size</title>
+
+      <para>It is sometime useful to know the total number of matching
+      documents:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>for the Google-like feature 1-10 of about 888,000,000 </para>
+        </listitem>
+
+        <listitem>
+          <para>to implement a fast pagination navigation</para>
+        </listitem>
+
+        <listitem>
+          <para>to implement a multi step search engine (adding approximation
+          if the restricted query return no or not enough results)</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>But it would be costly to retrieve all the matching
+      documents.</para>
+
+      <para>Hibernate Search allows you to retrieve the total number of
+      matching documents regardless of the pagination parameters. Even more
+      interesting, you can retrieve the number of matching elements without
+      even triggering a single object load.</para>
+
+      <programlisting>org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
+assert 3245 == <emphasis role="bold">query.getResultSize()</emphasis>; //return the number of matching books without loading a single one
+
+org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
+query.setMaxResult(10);
+List results = query.list();
+assert 3245 == <emphasis role="bold">query.getResultSize()</emphasis>; //return the total number of matching books regardless of pagination</programlisting>
+
+      <para></para>
+    </section>
+  </section>
+
+  <section>
+    <title>Optimizing the query process</title>
+
+    <para>Query performance depends on several criteria:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>the Lucene query itself: read the literature on this
+        subject</para>
+      </listitem>
+
+      <listitem>
+        <para>the number of object loaded: use pagination (always ;-) ) or
+        index projection (if needed)</para>
+      </listitem>
+
+      <listitem>
+        <para>the way Hibernate Search interacts with the Lucene readers:
+        defines the appropriate <xref
+        linkend="search-architecture-readerstrategy" />.</para>
+      </listitem>
+    </itemizedlist>
+  </section>
 </chapter>
\ No newline at end of file

Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/reader/ReaderProvider.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/reader/ReaderProvider.java	2007-05-30 20:25:23 UTC (rev 11599)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/reader/ReaderProvider.java	2007-05-31 02:48:08 UTC (rev 11600)
@@ -12,6 +12,8 @@
  * <p/>
  * Not that the reader must be closed once opened.
  *
+ * The ReaderProvider implementation must have a no-arg constructor
+ *
  * @author Emmanuel Bernard
  */
 public interface ReaderProvider {




More information about the hibernate-commits mailing list