Solr sort by the value of function query does not work
Asked Answered
B

1

2

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 
Bander answered 21/10, 2016 at 18:31 Comment(3)
Sorting by TextFields will not work as you expect, unless the field is keywordtokenized. Use a StrField for sorting if possible.Postconsonantal
I can change them to StrField but is it possible to achieve this sort function using StrField? I tried StrField and got the same exceptionBander
your question is related to this SO question. The way that the sorting is currently built in lucene, doesn't allow anything else than doubles to be used for searching. This is the reason why the sort function if(exists(firstname), firstname, lastname) asc can't work and solr returns UnsupportedOperationException at FunctionValues#doubleVal(int) method.Polled
J
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
Jewish answered 21/10, 2016 at 21:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.