Solr sort by the value of function query does not

2019-09-11 05:00发布

问题:

I'm working on a feature which relies on sorting the value of function query.

Function query is as below :

http://localhost:8983/solr/collection/select?q=*:*&sort=if(exists(f1_t), f1_t, theme)+ASC&wt=json&indent=true

The sort function is "if(exists(f1_t), f1_t, theme) ASC"

So basically what I'm doing is if the field "f1_t" (which is a dynamic field of type TextField) exists then the sorting is based on the value of the field else the sorting is based on the value of "theme" which is also a TextField (but it is not a dynamic field)

But when I run this it fails with the below exception. I tried the "if" function with integer values and it works fine. I was just wondering if you could help me figure out why the above function query fails? How can I get this working?

Solr version I'm using is 4.6.1

"trace": "java.lang.UnsupportedOperationException\n\tat
org.apache.lucene.queries.function.FunctionValues.doubleVal(FunctionValues.java:47)\n\tat 
org.apache.lucene.queries.function.valuesource.IfFunction$1.doubleVal(IfFunction.java:83)\n\tat 
org.apache.lucene.queries.function.ValueSource$ValueSourceComparator.copy(ValueSource.java:152)\n\tat 
org.apache.lucene.search.TopFieldCollector$OneComparatorNonScoringCollector.collect(TopFieldCollector.java:86)\n\tat 
org.apache.lucene.search.Scorer.score(Scorer.java:65)\n\tat 
org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:621)\n\tat 
org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:297)\n\tat 
org.apache.solr.search.SolrIndexSearcher.getDocListNC(SolrIndexSearcher.java:1529)\n\tat 
org.apache.solr.search.SolrIndexSearcher.getDocListC(SolrIndexSearcher.java:1395)\n\tat 
org.apache.solr.search.SolrIndexSearcher.search(SolrIndexSearcher.java:474)\n\tat 
org.apache.solr.handler.component.QueryComponent.process(QueryComponent.java:438)\n\tat 
org.apache.solr.handler.component.SearchHandler.handleRequestBody(SearchHandler.java:208)\n\tat 
org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:135)\n\tat org.apache.solr.core.SolrCore.execute(SolrCore.java:1859)\n\tat 
org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:723)\n\tat 
org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:419)\n\tat 
org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:203)\n\tat 
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1419)\n\tat 
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455)\n\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)\n\tat 
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)\n\tat 
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)\n\tat 
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)\n\tat 
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)\n\tat 
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)\n\tat 
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)\n\tat 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)\n\tat 
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)\n\tat 
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)\n\tat 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)\n\tat org.eclipse.jetty.server.Server.handle(Server.java:368)\n\tat 
org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)\n\tat 
org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)\n\tat 
org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:942)\n\tat 
org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1004)\n\tat 
org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:640)\n\tat 
org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)\n\tat 
org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)\n\tat 
org.eclipse.jetty.server.bio.SocketConnector$ConnectorEndPoint.run(SocketConnector.java:264)\n\tat 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)\n\tat 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)\n\tat java.lang.Thread.run(Thread.java:662)\n",
    "code": 500 

回答1:

I'm looking at the IfFunction$1.doubleVal(IfFunction.java:83) line and I think that the case is about Function Query restriction. It could operate on numeric fields as one can see in the Function Query wiki:

Function queries enable you to generate a relevancy score using the actual value of one or more numeric fields.

Since you know the fields you are going to use in advance you could solve this particular problem at index-time. In other words create surrogate sorting field, which will take value:

  • from user_h1_t field if f1_t field exists
  • from theme field otherwise