ES总结四:检索

全文查询

match

举一个例子,比如说存在某文档标题为:java编程思想。如果使用term query查询‘java编程思想’,查不到匹配性。因为term查询的是词项,java编程思想分词后会变成java、编程,思想、等词,所以Java编程思想查询不到,相反的是有match query 查询 java编程思想就可以查询的到。match会对查询语句进行分词,分词后查询语句中的任何一个词项被匹配,文档就会被搜索到。

match_phrase

match_phrase首先会把query内容分词,分词器可以自定义,同时文档还要满足以下两个条件才会被搜索到
1)分词后所有词项都要出现在该字段中。
(2)字段中的词项顺序要一致

match_phrase_prefix

match_phrase_prefix和match_phrase类似,只不过match_phrase_prefix支持最后一个term前缀匹配:

multi_match

multi_match是match的升级,用于搜索多个字段.。

query_string

querystringquery是与Lucene查询语句的语法结合非常紧密的一种查询,允许在一个查询语句中使用多个特殊条件关键字(如:AND|OR|NOT)对多个字段进行查询,建议熟悉Lucene查询语法的用户去使用.

simple_query_string

simple_query_string是一种适合直接暴露给用户,并且具有非常完善的查询语法的查询语句,接受Lucene查询语法,解析过程中发生错误不会抛出异常

词项查询

全文搜索在执行查询之前会分析查询字符串,词项搜索时对倒排索引中存储的词项进行精确操作。词项级别的查询通常用于结构化数据,如数字、日期和枚举类型。

term

term查询用来查找指定字段中包含给定单词的文档,term查询不被解析,只有查询词和文档中的词精确匹配才会被搜索到,应用场景为查询人名、地名等需要精准配备的需求。

terms

字段中包含关键词“java”或“python”的文档,构造查询语句如下:
GETbooks/search

{
    "query": {
        "terms": {
            "title": ["java", "python"]
        }
    }
}

range

range查询用于匹配在某一范围内的数值型、日期类型或者字符串型字段的文档,比如搜索哪些书籍的价格在50到100之间、哪些书籍的出版时间在2014年到2016年之间。使用range查询只能查询一个字段,不能作用在多个字段上。range查询支持的参数有以下几种:
•gt大于,查询范围的最小值,也就是下界,但是不包含临界值。
•gte大于等于,和gt的区别在于包含临界值。
•It小于,查询范围的最大值,也就是上界,但是不包含临界值。
•lte小于等于,和It的区别在于包含临界值
例如,想要查询价格大于50小于等于70的书籍,即50<price<=70, 构造查询语句如下:
GETbooks/search

{
    "query": {
        "range": {
            "price": {
                "gt": 50,
                "lte": 70
            }
        }
    }
}

查询出版日期在2016年1月1日和2016年12月31之间的书籍,对publish_time字段进行range查询:

{
    "query": {
        "range": {
            "pub1ish_time": {
                "gte": "2016-01-01",
                "lte": "2016-12-31",
                "format": "yyyy-MM-dd"
            }
        }
    }
}

exists

exists查询会返回字段中至少有一个非空值的文档

{
    "query": {
        "exists": {
            "field": "user"
        }
    }
}

user字段不为空的文档会被匹配出来

prefix

prefix查询用于查询某个字段中以给定前缀开始的文档,比如查询title中含有以java为前缀的关键词的文档,那么含有javajavascriptjavaee等所有以java开头关键词的文档都会被匹配

{
    "query": {
        "prefix": {
            "description": "win"
        }
    }
}

wildcard

假设需要找某一作者写的书,但是忘记了作者名字的全称,只记住了前两个字,那么就可以使用通配符查询:

{
    "query": {
        "wildcard": {
            "author": "张三*"
        }
    }
}

regexp

例如需要匹配以W开头紧跟着数字的邮政编码,使用正则表达式查询构造查询语句如下:

{
    "query": {
        "regexp": {
            "postcode": "W[0-9].+"
        }
    }
}

fuzzy

举例如下,用户在输入查询关键词时不小心把“javascript”拼成“javascritp”,在存在拼写错误的情况下使用模糊查询仍然可以搜索到含有“javascript”的文档,查询语句如下:

{
    "query": {
        "fuzzy": {
            "title": "javascritp"
        }
    }
}

复合查询

复合查询就是把一些简单查询组合在一起实现更复杂的查询需求,除此之外复合查询还可以控制另外一个查询的行为;

constant—score

constant——score query可以包装一个其他类型的查询,并返回匹配过滤器中的查询条件且具有相同评分的文档。下面的查询语句会返回title字段中含有关键词“java”的文档,所有文档的评分都是1.2

{
    "query": {
        "constantscore": {
            "filter": {
                "term": {
                    "title": "java"
                }
            },
            "boost": 1.2

        }
    }
}

bool

bool查询可以把任意多个简单查询组合在一起,使用must、should、must_not、filter选项来表示简单查询之间的逻辑,每个选项都可以出现0次到多次,它们的含义如下:

  • must:文档必须匹配must选项下的查询条件,相当于逻辑运算的AND
  • should:文档可以匹配should选项下的查询条件也可以不匹配,相当于逻辑运算的OR
  • must_not:与must相反,匹配该选项下的查询条件的文档不会被返回。
  • filter: 和must—样,匹配filter选项下的查询条件的文档才会被返回,但是filter不评分,只起到过滤功能
    假设要查询title中包含关键词java,并且price不能高于70,description可以包含也可以不包含虚拟机的书籍,构造bool查询语句如下:
    {
      "query": {
          "bool": {
              "minimu_should_match": 1,
              "must": {
                  "match": {
                      "title": "java"
                  }
              },
              "should": [{
                  "match": {
                      "description": "虚拟机"
                  }
              }],
              "must_not ": {
                  "range": {
                      "price": {
                          "gte": 70
                      }
                  }
              }
          }
      }
    }
    

    indices

    indicesquery适用于需要在多个索引之间进行查询的场景,它允许指定一个索引名字列表和内部查询。indicesquery中有query和nomatchquery两部分,query中用于搜索指定索引列表中的文档,no_match_query中的查询条件用于搜索指定索引列表之外的文档。下面的查询语句实现了搜索索引booksbooks2中title字段包含关键字javascript,其他索引中title字段包含basketball的文档,查询语句如下:
    {
      "query": {
          "indices": {
              "indices": ["book","book1"],
              "query":{"match":{"title":"javascript"}},
              "no_match_query":{"term":{"title":"basketball"}
          }
      }
    }
    

    其他查询

    除了上面讲到的查询之外,ES还有一些其他不常用查询,如嵌套查询、位置查询,特殊查询等等。

搜索排序

单字段排序

Elasticsearch是按照查询和文档的相关度进行排序的,默认按评分降序排序,搜索title字段中包含java关键词的文档:

{
    "query": {
        "term": {
            "title": "java"
        }
    }
}

等价于:

{
    "query": {
        "term": {
            "title": "java"
        }
    },
    "sort": [{
        "_score": {
            "order": "asc"
        }
    }]
}

对于match_all y而言,由于只返回所有文档,不需要评分,文档的顺序为添加文档的顺序。如果需要改变match_all的文档返回顺序,可以对_doc进行排序。例如,返回最后添加的那条文档,可以对_doc降序排序,设置返回文档条数为1,命令如下:

{
    "query": {
        "match_all": {}
    },
    "sort": [{
        "_doc": {
            "order": "desc"
        }
    }]
}

多字段排序

例如,先按价格降序排序,价格相等的按照出版年份升序排序:

{
    "sort": [{
        "price": {
            "order": "asc"
        }
    }, {
        "year": {
            "order": "desc"
        }
    }]
}