返回顶部

ES高级操作

结果过滤

默认情况下,elasticsearch在搜索的结果中,会把文档中保存在_source的所有字段都返回。

如果我们只想获取其中的部分字段,我们可以添加_source的过滤

直接指定字段

示例:

POST /heima/_search
{
  "_source": ["title","price"],
  "query": {
    "term": {
      "price": 2699
    }
  }
}

返回的结果:  

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "3q3hTW0BTp_XthqB2lMR",
        "_score": 1,
        "_source": {
          "price": 2699,
          "title": "小米手机"
        }
      }
    ]
  }
}

指定includes和excludes

我们也可以通过:

  • includes:来指定想要显示的字段
  • excludes:来指定不想要显示的字段

二者都是可选的。

示例:

POST /heima/_search
{
  "_source": {
    "includes":["title","price"]
  },
  "query": {
    "term": {
      "price": 2699
    }
  }
}

与下面的结果将是一样的:  

POST /heima/_search
{
  "_source": {
     "excludes": ["images"]
  },
  "query": {
    "term": {
      "price": 2699
    }
  }
}

结果:  

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "3q3hTW0BTp_XthqB2lMR",
        "_score": 1,
        "_source": {
          "price": 2699,
          "title": "小米手机"
        }
      }
    ]
  }
}

 高级查询

布尔组合(bool)

bool把各种其它查询通过must(与)、must_not(非)、should(或)的方式进行组合  

GET /heima/_search
{
    "query":{
        "bool":{
            "must":     { "match": { "title": "小米" }},
            "must_not": { "match": { "title":  "电视" }},
            "should":   { "match": { "title": "手机" }}
        }
    }
}

结果:  

{
  "took": 134,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.0884295,
    "hits": [
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "3q3hTW0BTp_XthqB2lMR",
        "_score": 1.0884295,
        "_source": {
          "title": "小米手机",
          "images": "http://image.leyou.com/12479122.jpg",
          "price": 2699
        }
      }
    ]
  }
}

范围查询(range)

range 查询找出那些落在指定区间内的数字或者时间

range查询允许以下字符:

操作符说明
gt 大于
gte 大于等于
lt 小于
lte 小于等于

示例:  

POST /heima/_search
{
    "query":{
        "range": {
            "price": {
                "gte":  3000,
                "lt":   5000
            }
        }
    }
}

结果:  

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "3a3hTW0BTp_XthqB2lMR",
        "_score": 1,
        "_source": {
          "title": "大米手机",
          "images": "http://image.leyou.com/12479122.jpg",
          "price": 3288
        }
      },
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "363hTW0BTp_XthqB2lMR",
        "_score": 1,
        "_source": {
          "title": "小米电视4A",
          "images": "http://image.leyou.com/12479122.jpg",
          "price": 4288
        }
      }
    ]
  }
}

模糊查询(fuzzy)

我们新增一个商品:  

POST /heima/goods/4
{
    "title":"apple手机",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":5899.00
}

fuzzy自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据

它允许用户搜索词条与实际词条出现偏差,但是偏差的编辑距离不得超过2:

POST /heima/_search
{
  "query": {
    "fuzzy": {
      "title": "appla"
    }
  }
}

上面的查询,也能查询到apple手机

fuzziness,你的搜索文本最多可以纠正几个字母去跟你的数据进行匹配,默认如果不设置,就是2我们可以通过

POST /heima/_search
{
  "query": {
    "fuzzy": {
      "title": {
        "value": "applaa",
        "fuzziness": 2
      }
    }
  }
}

 排序

单字段排序

sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式 

POST /heima/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {"price": {"order": "desc"}}
  ]
}

多字段排序

假定我们想要结合使用 price和 _score(得分) 进行查询,并且匹配的结果首先按照价格排序,然后按照相关性得分排序:  

POST /heima/_search
{
    "query":{
        "match_all":{}
    },
    "sort": [
      { "price": { "order": "desc" }},
      { "_score": { "order": "desc" }}
    ]
}

高亮

elasticsearch中实现高亮的语法比较简单:  

POST /heima/_search
{
  "query": {
    "match": {
      "title": "电视"
    }
  },
  "highlight": {
    "pre_tags": "<font color='pink'>",
    "post_tags": "</font>",
    "fields": {
      "title": {}
    }
  }
}

在使用match查询的同时,加上一个highlight属性:

  • pre_tags:前置标签

  • post_tags:后置标签

  • fields:需要高亮的字段

    • title:这里声明title字段需要高亮,后面可以为这个字段设置特有配置,也可以空

结果:  

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.90204775,
    "hits": [
      {
        "_index": "heima",
        "_type": "goods",
        "_id": "363hTW0BTp_XthqB2lMR",
        "_score": 0.90204775,
        "_source": {
          "title": "小米电视4A",
          "images": "http://image.leyou.com/12479122.jpg",
          "price": 4288
        },
        "highlight": {
          "title": [
            "小米<font color='pink'>电视</font>4A"
          ]
        }
      }
    ]
  }
}

分页

elasticsearch中实现分页的语法非常简单:  

POST /heima/_search
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "from": 0
}

size:每页显示多少条

from:当前页起始索引, int start = (pageNum - 1) * size;

 小案例

制作测试数据

PUT /goods/fruit/1
{
  "name": "xiangjiao",
  "describe": "haochi tian",
  "price": 40,
  "producer": "feilvbin",
  "tags": [
    "xiangjiao",
    "haochi"
  ]
}
 
 
PUT /goods/fruit/2
{
  "name":"pingguo",
  "describe":"cui",
  "price":60,
  "producer":"zhongguo",
  "tags":["haokan","xiang"]
}
 
PUT /goods/fruit/3
{
  "name":"lizi",
  "describe":"zide",
  "price":10,
  "producer":"zhongguo",
  "tags":["suan","tian"]
}
 
PUT /goods/fruit/4
{
  "name":"boluo",
  "describe":"getouda",
  "price":74,
  "producer":"malaxiya",
  "tags":["huang","youci"]
}
 
PUT /goods/fruit/5
{
  "name":"mihoutao",
  "describe":"suan",
  "price":45,
  "producer":"xinxilan",
  "tags":["lv","huang"]
}
 
PUT /goods/fruit/6
{
  "name":"xigua",
  "describe":"haochi",
  "price":109,
  "producer":"zhongguo",
  "tags":["da","haochi"]
}
View Code

查询所有数据

GET goods/fruit/_search
{
  "query": {
    "match_all": {}
  }
}

 排序查询

GET goods/fruit/_search
{
  "query": {
    "match": {
      "name": "pingguo"
    }
  },
  "sort": {
    "price": {
      "order": "asc"
    }
  }
}

每页显示2条数据,无序的话,按照默认排序  

GET goods/fruit/_search
{
  "query": {
    "match": {
      "name": "pingguo"
    }
  },
  "sort": {
    "price": {
      "order": "asc"
    }
  },
  "from": 0,
  "size": 2
}

使用 “_source” 查询指定字段的数据  

GET goods/fruit/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["name", "producer"]
}

bool查询

bool的方式,根据指定字段查询数据。

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "pingguo"
          }
        }
      ]
    } 
  }
}

bool多条件查询,相当于sql的and语句。  

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "pingguo"
          }
        },
        {
          "match": {
            "producer": "zhongguo"
          }
        }
      ]
    } 
  }
}

 bool多条件或查询,相当于sql的or语句

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "name": "pingguo"
          }
        },
        {
          "match": {
            "producer": "zhongguo"
          }
        }
      ]
    } 
  }
}

 bool多条件非查询,相当于sql的not语句

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "name": "pingguo"
          }
        },
        {
          "match": {
            "producer": "zhongguo"
          }
        }
      ]
    } 
  }
}

按条件查询

查询name是pingguo的,然后价钱大于100的数据(里可以使用should但是不建议使用should,会出现异常错误)  

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "pingguo"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gt": 100
            }
          }
        }
      ]
    }
  }
}

短语检索

通过检索数组类型的数据,可直接通过全文检索,匹配多个值,通过空格间隔。  

GET goods/fruit/_search
{
  "query": {
    "match": {
      "tags": "da lv"
    }
  }
}

 短语匹配,就像 match 查询对于标准全文检索是一种最常用的查询一样,当你想找到彼此邻近搜索词的查询方法时,就会想到 match_phrase 查询。

GET goods/fruit/_search
{
  "query": {
    "match_phrase": {
      "name": "pingguo"
    }
  }
}

高亮显示(highlight)

GET goods/fruit/_search
{
  "query": {
    "match": {
      "name": "pingguo"
    }
  },
  "highlight": {
    "pre_tags": "<b style='color: red'>",
    "post_tags": "</b>",
    "fields": {
      "name": {}
    }
  }
}

聚合函数(先查询,在聚合,分段式)

查询出来的数据,选择指定字段计算平均值,例如计算价钱平均值。  sum 总数,avg 平均值

前20的平局值 

GET goods/fruit/_search
{
  "from": 0,
  "size": 20,
  "aggs": {
    "avg_price": {
      "avg": {
        "field": "price"
      }
    }
  }
}

默认会同时展示计算结果与查询出来的数据,如果不想要查询出来的数据,将 size 设置为0  

 bool查询后,进行聚合函数处理(查询苹果价格大于100的价格总数)

GET goods/fruit/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "pingguo"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 100
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "c": {
      "sum": {
        "field": "price"
      }
    }
  }
}

分段查询后,进行聚合函数处理 

GET goods/_search
{
  "size": 0,
  "aggs": {
    "f": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "from": 0,
            "to": 50
          },
          {
            "from": 50,
            "to": 100
          },
          {
            "from": 100,
            "to": 150
          }
        ]
      },
      "aggs": {
        "sum_price": {
          "sum": {
            "field": "price"
          }
        }
      }
    }
  }
} 

输出结果如下  

{
  "took" : 11,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 7,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "f" : {
      "buckets" : [
        {
          "key" : "0.0-50.0",
          "from" : 0.0,
          "to" : 50.0,
          "doc_count" : 3,
          "sum_price" : {
            "value" : 95.0
          }
        },
        {
          "key" : "50.0-100.0",
          "from" : 50.0,
          "to" : 100.0,
          "doc_count" : 2,
          "sum_price" : {
            "value" : 134.0
          }
        },
        {
          "key" : "100.0-150.0",
          "from" : 100.0,
          "to" : 150.0,
          "doc_count" : 2,
          "sum_price" : {
            "value" : 218.0
          }
        }
      ]
    }
  }
}
View Code

mapping

查询mapping

GET goods/_mapping

 新建mappings

dynamic的三个参数

  • 1. false 不会为新增的字段数据不会创建索引(也就是用不存在mapping中的字段检索是检索不出来的)

  • 2. true 会为所有数据属性创建索引,包括新建的字段属性

  • 3. strict 必须添加指定的属性,添加动态属性的时候,会报错。

PUT my_index1
{
  "mappings": {
    "a": {
      "dynamic": false,
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

copy_to属性

copy_to属性,把当前属性的值复制给指定的字段

PUT my_index2
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "first_name": {
          "type": "text",
          "copy_to":"full_name"
        },
        "last_name": {
          "type": "lotextng"
        },
         "full_name": {
          "type": "lotextng"
        }
      }
    }
  }
}

index属性

index属性,默认为true,如果设置为false,则当前属性不能被创建索引。及不能通过当前属性进行数据的筛选、搜索、查询等操作  

PUT my_index2
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "first_name": {
          "type": "text",
          "index": true
        },
        "last_name": {
          "type": "text",
          "index": false
        }
      }
    }
  }
}

对象型属性

创建对象型数据  

PUT my_index3/doc/2
{
  "name": "tom",
  "age": 11,
  "add": {
    "address": "bj",
    "tel": "13333333333"
  }
}

根据嵌套的属性数据进行过滤查询  

GET my_index3/doc/_search
{
  "query": {
    "match": {
      "add.address": "bj"
    }
  }
}

 ik分词器

ik分词器是按照词来分,单个字查不出来,es默认是按照字来分单个汉子也能查出来

创建mapping

PUT my_index7
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "content": {
          "type": "text",
          "analyzer":"ik_max_word"
        }
      }
    }
  }
}

添加数据  

PUT my_index7/doc/1
{
  "content":"今天是个好日子"
}


PUT my_index7/doc/2
{
  "content":"心想的事儿都能成"
}

模糊查询

GET my_index7/_search
{
  "query": {
    "match": {
      "content": "日子"
    }
  }
}

单个查不出来 

GET my_index7/_search
{
  "query": {
    "match": {
      "content": "日"
    }
  }
}

es默认的分词器

PUT my_index8
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "content": {
          "type": "text"
        }
      }
    }
  }
}

PUT my_index8/doc/1
{
  "content":"心想的事儿都能成"
}


GET my_index8/_search
{
  "query": {
    "match": {
      "content": "事"
    }
  }
}

 ik 最粗粒度分词,内容文章类的使用,标题的使用细的分词粒度

_all 不用重复定义,全局通用

PUT my_index9/
{
  "mappings": {
    "doc": {
      "_all": {
        "analyzer": "ik_smart"
      },
      "properties": {
        "content": {
          "type": "text"
        }
      }
    }
  }
}

短语查询和前缀查询  

中文来说尽量使用短语查询

GET my_index8/_search
{
  "query": {
    "match_phrase": {
      "content": "心想"
    }
  }
}

类似上面

GET my_index8/_search
{
  "query": {
    "match_phrase_prefix": {
      "content": "心想"
    }
  }
}

 

posted @ 2021-03-10 22:13  Crazymagic  阅读(330)  评论(0编辑  收藏  举报