Cannot find the overridden analyzer when using overridesForField

For entity class I declare two analyzers, one is for indexing, another is for searching(query builder).


@AnalyzerDefs({
        @AnalyzerDef(name = "nameAnalyzer",
                tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
                filters = {
                        @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
                        @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                        @TokenFilterDef(
                                factory = EdgeNGramFilterFactory.class, // Generate prefix tokens
                                params = {
                                        @Parameter(name = "minGramSize", value = "1"),
                                        @Parameter(name = "maxGramSize", value = "8")
                                }
                        )
                }

        ),

        @AnalyzerDef(name = "nameAnalyzer_query",
                tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
                filters = {
                        @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
                        @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                }
        ),
})

For entity field, I just declare like this:

@Column(nullable = false, length = 50)
@Field(name = "firstName", index = Index.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "nameAnalyzer"))
    private String firstName;

For query building, if I want to override field with a new analyzer like:

 EntityContext entityContext = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
                 .forEntity(Contact.class);

entityContext = entityContext.overridesForField("firstName", "nameAnalyzer_query");

It will throw non pointer exceptions, I check the log, it says the entity context could be found for “nameAnalyzer_query” analyzer.

But When I add a new @filed in that entity class like

@Column(nullable = false, length = 50)
    @Fields({
            @Field(name = "firstName", index = Index.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "nameAnalyzer")),
            @Field(name = "firstNameSearchField", index = Index.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "nameAnalyzer_query"))
    })
    private String firstName;

It works !!!

My question is

  1. what is the reason for that?
  2. Adding a new field annotation is the correct way to solve that?

I am using 5.9.1.Final for hibernate search.

Are you using the Elasticsearch integration?
Also, could you please provide the full stack trace?

09:27:20.404 [http-nio-8080-exec-3] DEBUG o.h.engine.internal.TwoPhaseLoad - Done materializing entity [au.com.mydesktop.userprofile.data.model.Agent#442648]
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at ch.qos.logback.access.servlet.TeeFilter.doFilter(TeeFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at au.com.mydesktop.http.filters.CorsFilter.doFilterInternal(CorsFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:84)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
	at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:254)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference.getElasticsearchAnalyzerReference(ScopedElasticsearchAnalyzerReference.java:121)
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference.access$200(ScopedElasticsearchAnalyzerReference.java:24)
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference$Builder.addAnalyzerReference(ScopedElasticsearchAnalyzerReference.java:111)
	at org.hibernate.search.query.dsl.impl.ConnectedQueryContextBuilder$HSearchEntityContext.overridesForField(ConnectedQueryContextBuilder.java:97)
	at au.com.mydesktop.contacts.repository.ContactHibernateSearchRepository.search(ContactHibernateSearchRepository.java:49)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl.findContactByOfficeIdAndSearchTerm(ContactHibernateSearchServiceImpl.java:87)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl$$FastClassBySpringCGLIB$$382f264c.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl$$EnhancerBySpringCGLIB$$8b4bb704.findContactByOfficeIdAndSearchTerm(<generated>)
	at au.com.mydesktop.contacts.controller.ContactController.searchContact(ContactController.java:227)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	... 59 more
09:27:20.421 [http-nio-8080-exec-3] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/v2] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference.getElasticsearchAnalyzerReference(ScopedElasticsearchAnalyzerReference.java:121)
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference.access$200(ScopedElasticsearchAnalyzerReference.java:24)
	at org.hibernate.search.elasticsearch.analyzer.impl.ScopedElasticsearchAnalyzerReference$Builder.addAnalyzerReference(ScopedElasticsearchAnalyzerReference.java:111)
	at org.hibernate.search.query.dsl.impl.ConnectedQueryContextBuilder$HSearchEntityContext.overridesForField(ConnectedQueryContextBuilder.java:97)
	at au.com.mydesktop.contacts.repository.ContactHibernateSearchRepository.search(ContactHibernateSearchRepository.java:49)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl.findContactByOfficeIdAndSearchTerm(ContactHibernateSearchServiceImpl.java:87)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl$$FastClassBySpringCGLIB$$382f264c.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
	at au.com.mydesktop.contacts.service.ContactHibernateSearchServiceImpl$$EnhancerBySpringCGLIB$$8b4bb704.findContactByOfficeIdAndSearchTerm(<generated>)
	at au.com.mydesktop.contacts.controller.ContactController.searchContact(ContactController.java:227)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at ch.qos.logback.access.servlet.TeeFilter.doFilter(TeeFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at au.com.mydesktop.http.filters.CorsFilter.doFilterInternal(CorsFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:84)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
	at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:254)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
{"@timestamp":"2018-07-12T09:27:20.421+10:00","log-type":"access","server-ip":"119.15.70.52","server-name":"localhost","server-port":"8080","auth":"-","response-time":137,"referrer":"-","request.agent":"PostmanRuntime/7.1.1","request.client-ip":"0:0:0:0:0:0:0:1","request.client-host":"0:0:0:0:0:0:0:1","request.host":"localhost:8080","request.url":"/v2/contacts/search/name","request.queryString":"?searchTerm=pau%20geo","request.protocol":"HTTP/1.1","request.method":"GET","request.accept":"*/*","request.accept-encoding":"gzip, deflate","request.content-type":"-","request.connection":"keep-alive","request.payload":"","response.code":500,"response.size-in-bytes":null,"response.content-type":"null","response.content-length":"null","response.payload":""}

Ok, so you are using the Elasticsearch integration. Then this behavior is, unfortunately, expected.

How to work it around

You can add another field with that analyzer, it will work and you can rely on that to work.

It will, however, create an unnecessary field in your schema, which may increase the storage use of your Elasticsearch noticeably depending on how much data is contained in this field. To mitigate that, you could just use the analyzer on a “dummy” field that will never have any content, like that:

/**
 * A dummy bridge that allows to define a field without adding any data to documents.
 * Allows to work around query analyzer issues, in particular.
 * See https://discourse.hibernate.org/t/cannot-find-the-second-analyzer-when-using/1043
 */
public class DummyStringBridge implements MetadataProvidingFieldBridge {
	@Override
	public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
		// No-op: this bridge does not index anything
	}

	@Override
	public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
		builder.field( name, FieldType.STRING );
	}
}

// Then in your entity class:
 
public class MyEntity {

    // ... 

    @Fields({
            @Field(name = "firstName", index = Index.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "nameAnalyzer")),
            @Field(name = "dummyFieldToAddQueryAnalyzer", index = Index.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "nameAnalyzer_query"), bridge = @FieldBridge(impl = DummyStringBridge.class)
    })
    private String firstName;

    // ... 
}

Then the dummy field will still be in your schema, but at least documents will never have any data for the dummy field.

Note I didn’t test this; if you do, I’d appreciate your feedback.

Another solution would be for you to use templates or alter the settings of the Elasticsearch indexes after Hibernate Search created them, but that’s much more complex. You’ll need to learn how to add templates or edit the settings of an index (caution: you may need to close the index before updating the settings) and how to configure an index to add analyzers.

Why is this happening?

The problem is that analyzers in Elasticsearch are defined per index, meaning we have to determine what analyzers are needed for each index in order to produce the configuration of each index. We can’t just send all analyzers to a global configuration and say “hey Elasticsearch, make these analyzers available on every index”.

In order to determine which analyzers are needed on each index, the only data available to Hibernate Search is the mapping. So if an analyzer is not used in the mapping (like your query-only analyzer, then it will not be considered as needed for the index, and you will get this error.

There is a ticket to try to improve that situation, but we will probably only be able to address it in the next major version of Hibernate Search, version 6: https://hibernate.atlassian.net/browse/HSEARCH-2534

Thanks yoann, it is very helpful to me, and I am looking forward to version 6