[elasticsearch] query_string으로 질의시 유의할 사항
elasticsearch에 질의할 때, freemarker를 이용하여 아래와 같이 json 질의를 할 수 있다.
{
"query": {
"filtered" : {
"query" : {
"query_string" : {
"query" : "${queryString}"
}
}
}
}
}
queryString에 사용자가 별의 별 단어를 넣을 수 있는데. 이 때 잘못하면 큰 이상한 문제를 야기할 수 있다.
즉, 사용자가 입력한 모든 내용을 검색해주다가 lucene 문법에 따라 다양한 wildcard, 연산자(and, or, not)로 cpu를 많이 소비할 수 있는데, 이를 escape처리할 수 있다.
처리 방법은 다음과 같다.
1. lucene 4에서는 QueryParser.escape() 메소드를 이용하여 escape 처리를 한다.
2. and, or, not 제거
참고:
Reserved charactersedit
If you need to use any of the characters which function as operators in your query itself (and not as operators), then you should escape them with a leading backslash. For instance, to search for (1+1)=2
, you would need to write your query as \(1\+1\)\=2
.
The reserved characters are: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
lucene4의 QueryParser의 escape()메소드
/**
* Returns a String where those characters that QueryParser
* expects to be escaped are escaped by a preceding <code>\</code>.
*/
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();