es03-搜索-过滤排序
就像在学习mysql的时候,学习查询语句比其他语句花费的时间要多,es的查询语句也是如此。
文档的搜索
URL参数条件搜索
- q:使用某个字段来进行查询,例如q:book_name=book,就是根据book_name中是否有book来- 进行搜索。
- sort:使用某个字段来进行排序,例如sort=cost:desc,就是根据cost字段来进行降序desc排序。
- 其他:fileds,timeout,analyzer【这些参数留在请求体搜索中讲】
- 不带参数时,为“全搜索”
- 多个参数使用&&拼接
例子
GET /douban/book/_search?q=book_summary:character
GET /douban/book/_search?q=book_author:Milan
GET /douban/book/_search?q=book_summary:a
GET /douban/book/_search?q=book_summary:a&&sort=book_pages:desc
GET /douban/book/_search?q=book_summary:a&&q=book_author:Milan
【值得注意的是,请先不要对text类型的数据进行排序,这会影响搜索,对整数排序即可,后面会再细讲】
请求体参数
语法和例子
//全搜索
GET /index/type/_search
GET /douban/book/_search
//全搜索
GET /index/type/_search
{
"query": {
"match_all": {}
}
}
GET /douban/book/_search
{
"query": {
"match_all": {}
}
}
// 查询指定字段的数据(全文搜索,如果搜索值有多个词,仅匹配一个词的结果也可以查询出来):
GET /index/type/_search
{
"query": {
"match": {
"字段名": "搜索值"
}
}
}
GET /douban/book/_search
{
"query": {
"match": {
"book_name": "A The"
}
}
}
// 使用同一搜索值搜索多个字段:
GET /index/type/_search
{
"query": {
"multi_match": {
"query": "搜索值",
"fields": [
"搜索的字段1","搜索的字段2"]
}
}
}
GET /douban/book/_search
{
"query": {
"multi_match": {
"query": "A",
"fields": [
"book_name","book_summary"]
}
}
}
// 短语查询:【搜索值必须完全匹配,不会把搜索值拆分来搜索】
GET /index/type/_search
{
"query": {
"match_phrase": {
"字段": "搜索值"
}
}
}
GET /douban/book/_search
{
"query": {
"match_phrase": {
"book_summary": "a character"
}
}
}
// 字段过滤,查询的结果只显示指定字段
GET /product/book/_search
{
"query": {
"查询条件"
},
"_source": [
"显示的字段1",
"显示的字段2"
]
}
GET /douban/book/_search
{
"query": {
"match": {
"book_name": "Story"
}
},
"_source": [
"book_name",
"book_id"
]
}
// 高亮查询:【根据查询的关键字来进行高亮,高亮的结果会显示在返回结果的会自动在返回结果中的highlight中,关键字会被加上<em>标签】
// 如果想要多字段高亮,也需要进行多字段搜索
GET /index/book/_search
{
"query": {
"查询条件"
},
"highlight": {
"fields": {
"高亮的字段名1": {}
}
}
}
GET /douban/book/_search
{
"query": {
"match": {
"book_summary": "Story"
}
},
"highlight": {
"fields": {
"book_summary":{}
}
}
}
GET /douban/book/_search
{
"query": {
"multi_match": {
"query": "Story",
"fields": [
"book_name","book_summary"]
}
},
"highlight": {
"fields": {
"book_summary":{},
"book_name":{}
}
}
}
前置知识:对于条件拼接,在SQL中有and,or,not,在ElasticSearch不太一样,下面逐一讲解:
bool:用来表明里面的语句是多条件的组合,用来包裹多个条件。
should:里面可以有多个条件,查询结果必须符合查询条件中的一个或多个。
must:里面的多个条件都必须成立
must_not:里面的多个条件必须不成立
// 书名必须包含Story的
GET /douban/book/_search
{
"query": {
"bool": {
"must": [
{
"match":{
"book_name":"Story"
}
}
]
}
}
}
// 书名必须不包含Story的
GET /douban/book/_search
{
"query": {
"bool": {
"must_not": [
{
"match":{
"book_name":"Story"
}
}
]
}
}
}
// 书名必须不包含Story,书名包含Adventures或Immortality的
GET /douban/book/_search
{
"query": {
"bool": {
"must_not": [
{
"match":{
"book_name":"Story"
}
}
],
"should": [
{
"match": {
"book_name": "Adventures"
}
},
{
"match": {
"book_name": "Immortality"
}
}
]
}
}
}
// 在should、must、must_not这些里面都可以放多个条件
GET /douban/book/_search
{
"query": {
"bool": {
"must_not": [
{
"match":{
"book_name":"Story"
}
},
{
"match": {
"book_name": "Adventures"
}
}
]
}
}
}
// 如果是单个条件的时候,还可以这样写,省去[]:
GET /douban/book/_search
{
"query": {
"bool": {
"must_not": {
"match":{
"book_name":"Story"
}
}
}
}
}
// 还可以条件嵌套,也就是再嵌套一层bool,不过要注意逻辑,例如:
// 查询出(书名有story)或者(书名有The而且作者名有David)的,第二个是可成立可不成立的。
GET /douban/book/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"book_name": "Story"
}
},
{
"bool": {
"must": [
{
"match": {
"book_name": "The"
}
},
{
"match": {
"book_author": "David"
}
}
]
}
}
]
}
}
}
- 上面主要讲解了:
- 基于bool、should、must、must_not的多条件搜索,上面的知识已经能基础地实现一些搜索功能了。
- 索指定分词器、给多条件指定匹配数量、滚动查询还没了解
文档的过滤filter
过滤的效果其实有点像条件搜索,不过条件搜索会考虑相关度分数和考虑分词,而过滤是不考虑这些的,过滤对相关度没有影响。过滤一般用于结构化的数据上,也就是通常不用于使用了分词的数据上,通常都会用在数值类型和日期类型的数据上。
- 例子
// range,gte是不小于,lte是不大于,eq是等于,gt是大于,lt是小于 GET / index/type/_search { "query": { "range": { "字段名": { "gte": 比较值 [,"lte": 比较值] } } } } GET /douban/book/_search { "query": { "range": { "book_pages": { "gte": 352, "lt":400 } } } } // term用于匹配字符串和数值型类型的数据(解决了range中没有eq的问题),但不能直接用于分词的字段。 //【这个并没有那么简单,会后续再讲,直接匹配一些会分词的字段时,会匹配失败, //因为这时候这个字段拿来匹配的都是散乱的值,不是完整的原本的字段数据,所以下面用了不分词的数值型的字段来演示】 GET /douban/book/_search { "query": { "term": { "字段": "搜索值" } } } GET /douban/book/_search { "query": { "term": { "book_pages": 352 } } } //terms GET /douban/book/_search { "query": { "terms": { "字段": ["搜索值1","搜索值2"] } } } GET /douban/book/_search { "query": { "terms": { "book_pages": [ "352", "400" ] } } }
- filter与bool
GET /douban/book/_search
{
"query": {
"bool": {
"must": [
{
"match":{
"book_name":"Story"
}
},
{
"range": {
"book_pages": {
"lte":300
}
}
}
]
}
}
}
GET /douban/book/_search
{
"query": {
"bool": {
"must": [
{
"match":{
"book_name":"Story"
}
},
{
"range": {
"book_pages": {
"lte":300
}
}
},
{
"term": {
"publish_date": "1994-02-01"
}
}
]
}
}
}
- constant_score
GET /douban/book/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"book_pages": {
"gte": 352,
"lt": 400
}
}
}
}
}
}
// boost设置filter提供的相关度score值
GET /douban/book/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"book_pages": {
"gte": 352,
"lt": 400
}
}
},
"boost": 1.2
}
}
}
- 过滤通常用于过滤结构化数据,也就是那些不分词的数据,
- 其中range用于数值范围过滤,term用于字符类型的数据或数值类型的数据的值是否相等
- terms是term的复数版。过滤也支持bool拼接多个条件。
- 过滤提供的相关度分数是一个常数,默认是1。
文档的聚合
mysql有聚合函数,es也可以聚合。
ElasticSearch中常见的聚合分析函数有terms(分组函数)、avg(平均数)、range(区间分组)、max(求最大值)、min(求最小值)、cardinality(获取唯一值的数量)、value_count(获取值的数量,不去重,可以得出多少个值参与了聚合)
- 例子
// 按性别分组 GET /douban/book/_search { "aggs": { "groud_by_express": { "terms": { "field": "book_id", "size": 10 } } } } //求年龄的平均数 GET /people/test/_search { "aggs": { "avg_of_age": { "avg": { "field": "age" } } } } // 求年龄的最大值: GET /people/test/_search { "aggs": { "max_of_age": { "max": { "field": "age" } } } } // 把年龄[15,17]的分成一组,把年龄[18,25]的分成一组 GET /people/test/_search { "aggs": { "range_by_age": { "range": { "field": "age", "ranges": [ { "from": 15, "to": 17 }, { "from": 18, "to": 25 } ] } } } } // 获取不同的年龄数:,比如有年龄[1,2,3,3,4,5],得到的结果是5,因为3只算一次 GET /people/test/_search { "aggs": { "get_diff_age_count": { "cardinality": { "field": "age" } } } }
其他语法
- 先查询后聚合
GET /people/test/_search { "query": { "match": { "name": "lilei1" } }, "aggs": { "avg_of_age": { "avg": { "field": "age" } } } }
- 先过滤后聚合
// 先获取年龄大于15的,再求平均值 GET /people/test/_search { "query": { "range": { "age": { "gt":15 } } }, "aggs": { "avg_of_age": { "avg": { "field": "age" } } } }
- 聚合函数嵌套
// 先按性别分组,再获取年龄平均值 GET /people/test/_search { "aggs": { "groud_by_express": { "terms": { "field": "gender" }, "aggs": { "avg_of_age": { "avg": { "field": "age" } } } } } }
- 聚合+排序
// 先按性别分组,再按分组的年龄平均值降序排序,order中的avg_of_age就是下面的聚合函数的自定义名称 GET /people/test/_search { "aggs": { "groud_by_express": { "terms": { "field": "gender", "order": { "avg_of_age": "desc" } }, "aggs": { "avg_of_age": { "avg": { "field": "age" } } } } } }
aggs是与query同级的,使用聚合函数需要自己定义一个外层的聚合函数名称,
avg用于求平均值,max用于求最大值,range用于范围分组,term用于数据分组。
分组可以与条件搜索和过滤一起使用,aggs是与query同级的,聚合函数也可以嵌套使用。
文档的分页、排序
分页
// 从第一条开始,获取两条数据
GET /people/test/_search
{
"from": 0,
"size": 2
}
// 可以先查询,再分页
GET /people/test/_search
{
"query": {
"match": {
"name": "lilei1"
}
},
"from": 0,
"size": 1
}
排序
排序处理:【sort与query同级别,是一个数组,里面可以有多个排序参数,参数以{"FIELD":{"order":"desc/asc"}}为格式】
GET /people/test/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
这小结主要讲使用from和size分页,使用sort排序