Escaping special characters in elasticsearch

18,026

Yes, those characters will need to be replaced within content you want to search in a query_string query. To do that (assuming you are using PyLucene), you should be able to use QueryParserBase.escape(String).

Barring that, you could always adapt the QueryParserBase.escape source code to your needs:

public static String escape(String s) {
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    // These characters are part of the query syntax and must be escaped
    if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
      || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
      || c == '*' || c == '?' || c == '|' || c == '&' || c == '/') {
      sb.append('\\');
    }
    sb.append(c);
  }
  return sb.toString();
}
Share:
18,026
Zack
Author by

Zack

hello world!

Updated on June 04, 2022

Comments

  • Zack
    Zack almost 2 years

    I am using the elasticsearch python client to make some queries to the elasticsearch instance that we are hosting.

    I noticed that some characters need to be escaped. Specifically, these...

    + - && || ! ( ) { } [ ] ^ " ~ * ? : \
    

    Is there a clean way to do this beyond what I've already got in mind? Surely there is a cleaner way than doing

    term
        .replace("+", "\+")
        .replace("-", "\-")
    
        # ....etc
    

    I was hoping there was an API call that I could use, but I can't find one in the docs. This seems like a common enough issue that it should have been solved by someone.

    Does anyone know the "correct" way of doing this?

    EDIT : I am still not sure if there is an API call, but I got things concise enough to where I am happy.

    def needs_escaping(character):                                                                                                                                                                                        
    
        escape_chars = {                                                                                                                                                                                               
            '\\' : True, '+' : True, '-' : True, '!' : True,                                                                                                                                                           
            '(' : True, ')' : True, ':' : True, '^' : True,                                                                                                                                                            
            '[' : True, ']': True, '\"' : True, '{' : True,                                                                                                                                                            
            '}' : True, '~' : True, '*' : True, '?' : True,                                                                                                                                                            
            '|' : True, '&' : True, '/' : True                                                                                                                                                                         
        }                                                                                                                                                                                                              
        return escape_chars.get(character, False)   
    
    
    sanitized = ''
    for character in query:                                                                                                                                                                                            
    
        if needs_escaping(character):                                                                                                                                                                                 
            sanitized += '\\%s' % character                                                                                                                                                                           
        else:                                                                                                                                                                                                      
            sanitized += character