# Autocomplete with Hibernate Search 6

**URL:** <https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006>\
**Category:** Hibernate Search\
**Created:** [February 2, 2021, 8:38am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006 "2021-02-02T08:38:27Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablo\_jaska](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pablo\_jaska](https://discourse.hibernate.org/u/pablo_jaska)\
**Post date:** [February 2, 2021, 8:38am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/1 "2021-02-02T08:38:27Z")

</div>

Hello with the last Hibernate version we implemented the autocomplete method as follows:

```auto
public List<String> getAllSuggestions(final String searchString) {
        IndexReader reader = null;
        try {
            final FullTextEntityManager fullTextEntityManager = Search
                .getFullTextEntityManager(emf.createEntityManager());
            reader = fullTextEntityManager.getSearchFactory().getIndexReaderAccessor().open(Entity.class);

            final Terms firstTerms= SlowCompositeReaderWrapper.wrap(reader)
                .terms("firstEntityField");
            final Terms secondTerms= SlowCompositeReaderWrapper.wrap(reader)
                .terms("secondEntityField");
            final Terms thirdTerms= SlowCompositeReaderWrapper.wrap(reader)
                .terms("thirdEntityField");

//All words are written in a set so that there are no duplicate entries (Helper-Method below)
            final Set<String> allTerms = new HashSet<>();
            addTermsToSet(firstTerms, allTerms);
            addTermsToSet(secondTerms, allTerms);
            addTermsToSet(thirdTerms, allTerms);

            final List<String> suggestions = allTerms.stream().sorted(Comparator.naturalOrder())
                .collect(Collectors.toList());
    
            return suggestions.stream().filter(s -> s.startsWith(searchString) && !s.equalsIgnoreCase(searchString))
                .limit(SUGGESTION_LIMIT)
                .collect(Collectors.toList());
        } catch (final Exception e) {
            LOG.warn("Terms for autocomplete function couldn't be loaded.");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (final Exception readerException) {
                "..."
                }
            }
        }
        return new ArrayList<>();
    }

// Helper Method for Set
    private void addTermsToSet(final Terms terms, final Set<String> set) throws IOException {
        final BytesRefIterator iterator;
        iterator = terms.iterator();
        BytesRef byteRef = null;
        while ((byteRef = iterator.next()) != null) {
            set.add(byteRef.utf8ToString());
        }
    }

```

Unfortunately I couldn’t find any further information on how I could do something like this with  
Hibernate-Search 6.

Do you have any idea?  
Thank you!

---

<div class="post-metadata">

**Author:** ![yrodiere](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/yrodiere/32/1760_2.png) [@yrodiere](https://discourse.hibernate.org/u/yrodiere)\
**Post date:** [February 2, 2021, 8:56am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/2 "2021-02-02T08:56:01Z")

</div>

Hello,

As far as I can tell, `SlowCompositeReaderWrapper` no longer exist in Lucene 8.

I’ve never used something like this to implement autocomplete, I generally run a query against user-provided terms to retrieve “approximate” matches and return the top matches to the user. [Here is an example for Hibernate Search 5](https://stackoverflow.com/a/54882465/6692043), it would be rather similar in Hibernate Search 6 except that you can take advantage of the [searchAnalyzer](https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#mapper-orm-directfieldmapping-search-analyzer).

We can consider exposing readers again in Hibernate Search 6.1 (to be released in alpha in the next few months), but in order to do that right, can you tell us what are you using the `Terms` for exactly?

---

<div class="post-metadata">

**Author:** ![pablo\_jaska](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pablo\_jaska](https://discourse.hibernate.org/u/pablo_jaska)\
**Post date:** [February 2, 2021, 11:09am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/3 "2021-02-02T11:09:58Z")

</div>

Hello and thanks for the fast reply. I edited the method above.  
What we want is access to individual words from the index of several fields combined.

---

<div class="post-metadata">

**Author:** ![yrodiere](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/yrodiere/32/1760_2.png) [@yrodiere](https://discourse.hibernate.org/u/yrodiere)\
**Post date:** [February 2, 2021, 11:33am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/4 "2021-02-02T11:33:49Z")

</div>

Okay then… this may work for small indices, but it will perform rather badly on large ones.

In general, I’d recommend a different approach involving a query. The main difference is that it doesn’t suggest terms, but entities. So if you type “jo” you won’t get “John” as a suggestion, but the entity representing the person “John Smith”. Then you can decide to display that entity as you see fit.

If you’re interested by this approach, read on.

If you really want to use `Terms` to collect indexed terms with Hibernate Search 6, you will have to wait until [HSEARCH-4065](https://hibernate.atlassian.net/browse/HSEARCH-4065) gets fixed (or come and discuss [on Zulip](https://hibernate.zulipchat.com/#narrow/stream/132092-hibernate-search-dev) how to contribute a patch to fix it 😉 ).

Alternatively, you can also switch to Elasticsearch, where you can use suggesters, which I covered briefly [here](https://stackoverflow.com/a/65183114/6692043).

Now, to implement autocomplete with queries:

1. Declare an appropriate analyzer in your [analysis configurer](https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-lucene-analysis-analyzers):

```auto
public class MyAnalysisConfigurer implements LuceneAnalysisConfigurer {
	@Override
	public void configure(LuceneAnalysisConfigurationContext context) {
		context.analyzer( "autocomplete-indexing" ).custom()
				.tokenizer( StandardTokenizerFactory.class )
				.tokenFilter( LowerCaseFilterFactory.class )
				.tokenFilter( SnowballPorterFilterFactory.class )
						.param( "language", "English" )
				.tokenFilter( ASCIIFoldingFilterFactory.class )
				.tokenFilter( EdgeNGramFilterFactory.class )
						.param( "minGramSize", "3" )
						.param( "maxGramSize", "7" );

		// Same as "autocomplete-indexing", but without the edge-ngram filter
		context.analyzer( "autocomplete-query" ).custom()
				.tokenizer( StandardTokenizerFactory.class )
				.tokenFilter( LowerCaseFilterFactory.class )
				.tokenFilter( SnowballPorterFilterFactory.class )
						.param( "language", "English" )
				.tokenFilter( ASCIIFoldingFilterFactory.class );
	}
}

```

1. Declare full-text fields with the appropriate analyzers:

```auto
@Indexed
public class MyEntity {

    @FullTextField(name = "firstEntityField_autocomplete,
            analyzer = "autocomplete-indexing", searchAnalyzer = "autocomplete-query")
    private String firstEntityField;

    @FullTextField(name = "secondEntityField_autocomplete,
            analyzer = "autocomplete-indexing", searchAnalyzer = "autocomplete-query")
    private String secondEntityField;

    @FullTextField(name = "thirdEntityField_autocomplete,
            analyzer = "autocomplete-indexing", searchAnalyzer = "autocomplete-query")
    private String thirdEntityField;

    // ... getters, setters ...
}

```

1. [Reindex](https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#mapper-orm-indexing-massindexer) your data
2. Query like this to retrieve only entities that match the given terms:

```java
String terms = ...; // User input
List<MyEntity> hits = Search.session( entityManager )
		.search( MyEntity.class )
		.where( f -> f.simpleQueryString()
				.fields( "firstEntityField_autocomplete",
						"secondEntityField_autocomplete",
						"thirdEntityField_autocomplete" )
				.matching( terms )
				.defaultOperator( BooleanOperator.AND ) )
		.fetchHits( 20 );

```

---

<div class="post-metadata">

**Author:** ![pablo\_jaska](https://avatars.discourse-cdn.com/v4/letter/p/0ea827/32.png) [@pablo\_jaska](https://discourse.hibernate.org/u/pablo_jaska)\
**Post date:** [February 2, 2021, 11:53am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/5 "2021-02-02T11:53:43Z")

</div>

I appreciate your answer! I will try this. Thanks again!!!

---

<div class="post-metadata">

**Author:** ![yrodiere](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/yrodiere/32/1760_2.png) [@yrodiere](https://discourse.hibernate.org/u/yrodiere)\
**Post date:** [September 23, 2021, 7:37am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/6 "2021-09-23T07:37:17Z")

</div>

FYI, the index reader can now be accessed from Hibernate Search, starting with version 6.1:

> **[Hibernate Search 6.1.0.Alpha1 is out, now with asynchronous, distributed...](https://in.relation.to/2021/09/10/hibernate-search-6-1-0-Alpha1/#lucene-reader)**
>
> We just published Hibernate Search 6.1.0.Alpha1,
> an alpha release of the next minor version of Hibernate Search.
> 
> 
> 
> The main feature of this new version
> is a new concept of "coordination" to perform automatic indexing in an asynchronous, distributed...

---

<div class="post-metadata">

**Author:** ![yrodiere](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/yrodiere/32/1760_2.png) [@yrodiere](https://discourse.hibernate.org/u/yrodiere)\
**Post date:** [September 8, 2022, 6:25am UTC](https://discourse.hibernate.org/t/autocomplete-with-hibernate-search-6/5006/7 "2022-09-08T06:25:04Z")

</div>

A post was split to a new topic: [Native Lucene search - no fields in TopDocs](https://discourse.hibernate.org/t/native-lucene-search-no-fields-in-topdocs/6643)
