How can I configure Solr to perform case-insensitive searches on field names (not values)?

Viewed 990

In my Solr core, I have a field defined like this:

<field name="firstName" type="text_general" multiValued="false" indexed="true" stored="true"/>

I can query this field using something like this: "firstName:nathan". However, I'd like to be able to also search on this field with any of these:

  • "FirstName:nathan"
  • "firstname:nathan"
  • "FIRSTNAME:nathan"

Is it possible to configure Solr to allow for case-insensitive searching on field names?

Note that I'm not asking about case-insensitive searching on the field's value - this question has already been answered many times on StackOverflow.

1 Answers

The short answer is no (as of Solr's default config)

The long answer is yes, BUT you'll need to code a little...

I guess the best option is to change it in your application before it hits Solr both in index and query time. But if indexing is under your control and querying is not, and you need Solr to handle this only in query time, you can customize the query parser for what you need. To do so, you'll need to:

1- Write a QParserPlugin:

package com.hoss.solr;

import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.LuceneQParserPlugin;
import org.apache.solr.search.QParser;

/**
 * @author alehoss
 */
public class MyQParserPlugin extends LuceneQParserPlugin {

    @Override
    public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
        return new MyQParser(qstr, localParams, params, req);
    }

}

2- Write a QParser:

package com.hoss.solr;

import org.apache.lucene.search.Query;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.LuceneQParser;
import org.apache.solr.search.SyntaxError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author alehoss
 */
public class MyQParser extends LuceneQParser {

    private static final Logger log = LoggerFactory.getLogger(MyQParser.class);

    public MyQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
        super(qstr, localParams, params, req);
    }

    @Override
    public Query parse() throws SyntaxError {
        String qstr = getString();
        if (qstr == null || qstr.length()==0) return null;
        log.warn("original query = " + qstr + "; querying for " + qstr.toLowerCase());
        setString(qstr.toLowerCase());
        return super.parse();
    }

}

3- Export this into a JAR and add it to your solr contrib/custom directory (you can create it with another name);

4- Reference it in your solrconfig.xml:

<lib dir="${solr.install.dir:../../../..}/contrib/custom" regex=".*\.jar" />

5- Change the query parser for the handler you want to customize (/select, for example). The important here is the defType parameter, which references myparser:

<requestHandler name="/select" class="solr.SearchHandler">
    <!-- default values for query parameters can be specified, these
         will be overridden by parameters in the request
      -->
    <lst name="defaults">
      <str name="echoParams">explicit</str>
      <str name="defType">myparser</str>
      <int name="rows">10</int>
      <!-- <str name="df">text</str> -->
    </lst>
.
.
.
</requestHandler>

6 - Uncomment or declare your queryParser:

<queryParser name="myparser" class="com.hoss.solr.MyQParserPlugin"/>

In this hurry example I didn't consider lowercasing only the field name. So it'll lowercase the entire query ('q' parameter), including the values, but if this is a problem (if you do have a field where tokens aren't lowercased), you can change the implementation and parse the query string to achieve your needs.

Another thing is, considering this example, you'll need to declare all your field names in lowercase, not with camel case like your example. It doesn't matter how the user do the input, the query will always be done with lowercase field name, so the field name must exist in your schema in this form.

With this you'll be able to search for any of these:

  • "FirstName:nathan"
  • "firstname:nathan"
  • "FIRSTNAME:nathan"

And the query will be performed always with "firstname:nathan". So, the definition of the field in your schema must be name="firstname"

Downside: you won't be able to search for a field name or dynamic field name that is indexed with capitalized letters, but if you control indexing, it's not a problem.

My example was built on top of LuceneParser (the default parser for Solr), but you can choose another one or create an entirely new. Here's some useful docs about this:

Oficial Solr doc about parsing: https://lucene.apache.org/solr/guide/6_6/query-syntax-and-parsing.html

Nice article with full example similar to the one posted here: https://medium.com/@wkaichan/custom-query-parser-in-apache-solr-4634504bc5da

Related