0
votes

I like to use Hibernate Search for implementing an sophisticated autosuggestion feature across multiple input fields on a web page. Each input field is for its own entity, let's say Country and City. There is a many-to-one relationship between both entities (countries contain cities).

The autosuggestion should work such that when typing e.g. a country name prefix and the city field is already filled, you get only suggestions for countries that have such a city (and vice versa).

The server side autosuggestion service should return list of projections (entityId, entityName) which are rendered into the input field (dropdown, whatever).

According to the schema and after having read the manual I tried the following index schema:

SearchMapping mapping = new SearchMapping();

    mapping.analyzerDef(...
    .entity(City.class).indexed().indexName("MyIndex")
        .property("cityId", ElementType.FIELD)
            .documentId()
            .name("id")
    .property("name", ElementType.FIELD)
            .documentId()
            .name("id")
        .property("country", ElementType.METHOD)
            .indexEmbedded()
    .entity(Country.class).indexed()
        .property("id", ElementType.FIELD)
            .documentId()
            .name("id")
        .property("name", ElementType.METHOD)
            .field()
            .name("name")

This mapping defines City to be the main entity, right?
I have indexed all cities and am able to query for them (also by combining both fields). However, I only get matches when querying for cities. i.e. when querying like fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(City.class).get();

This is not useful for the country field becuse when I type in "Spain", I get a single row for each city of Spain. (Spain, Spain, Spain, Spain ,.... ;-))

The question is: How is it possible to search for country entities? Changing the index structure? The indexing procedure? Or how to query?

The only way I found was to setup a Facet for country, and you the different possible facets as autosuggestion. However, this is also not perfect since it is not possible to sort facets alphabetically.

Of course, in this example, I could switch both entities in the mapping, but suppose scenarios with more complex entity graphs.

UPDATE: adding queries requested in comment

For building queries, I employ the QueryBuilder. The following produces a result set like in the Spain example:

fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(City.class).get();

with query:

country.name:Spain

If I try to use a query builder for countries

fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Country.class).get();

and query:

name:Spain

I get no results.

1

1 Answers

1
votes

You are not showing your actual query. You don't have to use the query DSL, but you can also write native Lucene queries. In both cases (DSL or native Lucene) you can combine queries via boolean logic. Embedded entities follow the java bean notation. The country name would for example in a city query be reached as country.name. Again, without your actual query it is hard to give any more specific feedback.

Last, but not least, facets can also be sorted alphabetically. Check FacetSortOrder.COUNT_DESC.