ESquery_stringmatch的区别之一

今天线上发现一个问题,从而引出对query_string 和 match 的区别的思考。

发展壮大离不开广大客户长期以来的信赖与支持,我们将始终秉承“诚信为本、服务至上”的服务理念,坚持“二合一”的优良服务模式,真诚服务每家企业,认真做好每个细节,不断完善自我,成就企业,实现共赢。行业涉及成都铜雕雕塑等,在成都网站建设公司成都全网营销推广、WAP手机网站、VI设计、软件开发等项目上具有丰富的设计经验。

curl -XGET 'http://localhost:9200/*/*/_search?pretty' -d '{
"from" : 0,
"size" : 10,
"fields" : ["title"],
"query": {
"query_string" : {
"query" : "100CrMo7 +圆钢",
"fields" : ["title"]
}               
}
}' | grep "100CrMo7"

在这个例子中,在title中查找包含100CrMo7,并且包含圆钢的数据。

curl -XGET 'http://localhost:9200/*/*/_search?pretty' -d '{
  "from" : 0,
  "size" : 10,
  "fields" : ["title"],
  "query": {
"query_string" : {
"query" : "100CrMo7 -圆钢",
"fields" : ["title"]
}               
  }
}' | grep "100CrMo7"

在这个例子中,在title中查找包含100CrMo7,但是不包含圆钢的数据。

注:替换为simple_query_string 结果好像不尽人意。有一两条数据 没有被过滤出。

而看下面的例子

curl -XGET 'http://localhost:9200/*/*/_search?pretty' -d '{
   "size" : 10,
   "fields" : ["title"],
      "query" : {
        "bool" : {
          "must" : {
            "match" : {
              "_all" : {
                "query" : "100CrMo7 -圆钢",
                "type" : "boolean",
                "operator" : "AND",
                "boost" : 1.0
              }
            }
          }
        }
      }
}' | grep "100CrMo7"

无论是100CrMo7 -圆钢还是 100CrMo7 +圆钢结果没有发生变化。

看文档解释如下:
The match family of queries does not go through a "query parsing" process. It does not support field name prefixes, wildcard characters, or other "advanced" features.

已就是说后者没有经过查询分析的这个过程。
所以如果你使用后者时加入了如下代码:QueryParser.escape(keyword.trim()) 时,如果关键字里有“-” 这么一个特殊符号,比如 100CrMo7-3, 那么你的查询结果可能就是空。 所以在使用QueryParser.escape(keyword.trim()) 要分情况。

我们看一下它的源代码:

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();
  }

因为符号-被转译了。

先看QueryStringQueryParser的解析过程。

ES  query_string  match的区别之一

再看MatchQueryParser类
ES  query_string  match的区别之一

后者没有转译特殊字符,就解释了使用QueryParser.escape(keyword.trim()) 查不到结果。
继续查看matchQuery.parse
ES  query_string  match的区别之一

它只是调用查询分析器(mapping里设置的)去解析各个字段。

点击parseContext.queryParser

ES  query_string  match的区别之一

看到有很多的解析包括 < >等符号。


本文名称:ESquery_stringmatch的区别之一
分享URL:http://csdahua.cn/article/giogih.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流