Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example using Hibernate Search #36

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Example using Hibernate Search #36

wants to merge 1 commit into from

Conversation

aklish
Copy link
Member

@aklish aklish commented May 7, 2022

Do Not Merge - Example

I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

@chirdeeptomar
Copy link

Really appreciate this @aklish works for me now, having looked at the settings, I guess the setting below did the trick.

hibernate.search.default.locking_strategy=single

This is how I am overriding, you are conditionally adding ConfigDataStore, wouldn't that automatically be set?

         @Override
            public DataStore getDataStore(MetaDataStore metaDataStore, AggregationDataStore aggregationDataStore, EntityManagerFactory entityManagerFactory) {
                DataStore jpaDataStore = new JpaDataStore(
                        entityManagerFactory::createEntityManager,
                        em -> new NonJtaTransaction(em, ElideStandaloneSettings.TXCANCEL)
                );

                SearchDataStore searchStore = new SearchDataStore(jpaDataStore, entityManagerFactory, true, 3, 50);

                return new MultiplexManager(metaDataStore, aggregationDataStore, searchStore);
            }

@chirdeeptomar
Copy link

So I can see the index is created and lucene files being created in the correct directory path. However when I search, its still firing a Hibernate query to the database. Is my understanding wrong on how this should behave or my query is incorrect?

Employee.java

@Data
@Entity
@Table(name = "employees")
@Include(name = "employee")
@Indexed
@AnalyzerDef(name = "case_insensitive",
        tokenizer = @TokenizerDef(factory = NGramTokenizerFactory.class, params = {
                @Parameter(name = "minGramSize", value = "3"),
                @Parameter(name = "maxGramSize", value = "10")
        }),
        filters = {
                @TokenFilterDef(factory = LowerCaseFilterFactory.class)
        }
)
@CreatePermission(expression = "User is Admin")
@UpdatePermission(expression = "User is Admin")
@DeletePermission(expression = "User is Admin")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;

    @Column(name = "name")
    private String name;

    @Fields({
            @Field(name = "name", index = Index.YES,
                    analyze = Analyze.YES, store = Store.NO, analyzer = @Analyzer(definition = "case_insensitive")),
            @Field(name = "sortName", analyze = Analyze.NO, store = Store.NO, index = Index.YES)
    })
    @SortableField(forField = "sortName")
    @Column(name = "email_address")
    private String emailAddress;
}
query {
  employeeSearchByEmail: employee(filter: "emailAddress=='a*'") {
    edges {
      node 
      {
        id
        emailAddress
       name
      }
    }
  }
}

@aklish
Copy link
Member Author

aklish commented May 24, 2022

Probably because the ngram min size is three:

@parameter(name = "minGramSize", value = "3")

Try adding more characters to your filter.

@chirdeeptomar
Copy link

I have added more characters to the query like so emailAddress=='ala*', emailAddress=='john' but no luck, still firing a hibernate query.

@aklish
Copy link
Member Author

aklish commented May 28, 2022

@chirdeeptomar
From Hibernate Search doc:
"Without projections, Hibernate Search will per default execute a Lucene query in order to find the database identifiers of the entities matching the query criteria and use these identifiers to retrieve managed objects from the database. The decision for or against projection has to be made on a case by case basis."

That explains why the DB query is happening.

@aklish
Copy link
Member Author

aklish commented May 28, 2022

Here is more information about projections in Hibernate search:

"Hibernate Search extracts the properties from the Lucene index and convert them back to their object representation, returning a list of Object[]. Projections avoid a potential database round trip (useful if the query response time is critical), but has some constraints:

the properties projected must be stored in the index (@field(store=Store.YES)), which increase the index size

the properties projected must use a FieldBridge implementing org.hibernate.search.bridge.TwoWayFieldBridge or org.hibernate.search.bridge.TwoWayStringBridge, the latter being the simpler version. All Hibernate Search built-in types are two-way.

you can only project simple properties of the indexed entity or its embedded associations. This means you cannot project a whole embedded entity.

projection does not work on collections or maps which are indexed via @IndexedEmbedded"

@aklish
Copy link
Member Author

aklish commented May 28, 2022

If you store all of the entity fields inside the lucene index (to avoid the database query), the index will become quite large. Furthermore, not all fields can be stored anyway (see limitations above). Querying lucene to identify the objects in the database - followed by a subsequent query to fetch those objects is a good tradeoff IMO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants