ElasticSearch的DSL语句-分词器操作 大全

DSL操作ES-操作索引库

# 创建索引库
PUT test

# 查看索引库
GET test

# 删除索引库
DELETE test

# 关闭索引库
POST  test/_close

# 打开索引库
POST test/_open

GET test/_search   # 查询全部
GET test/_mapper   #查询映射数据

DSL操作ES-区分类型-操作映射

1)简单数据类型:

 text:可以分词,不支持聚合(统计)

keyword:不会分词,将全部内容作为一个词条,支持聚合(统计) name keyword

布尔(boolean)

二进制(binary)

范围类型(integer_range, float_range, long_range, double_range, date_range)

日期(date)

2)复杂数据类型

  • 数组 []:没有专用的array数据类型,任何一个字段的值,都可以被添加0个到多个,但要求他们的类型必须一致,当类型一直含有多个值存储到ES中会自动转化成数组类型 ["eric","jack"] List Set

  • 对象 {} Map User {key:value,key:value}

3)GEO: geo_point 地理位置坐标值

简单试水:

# 创建一个person的索引库,并且有映射
PUT person
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "integer"
      }      
    }
  }
}

# 查看映射
GET person/_mapping

# 添加字段
PUT person/_mapping
{
  "properties":{
    "sex":{
      "type":"keyword"
    }
  }
}

添加文档,指定id 
POST person/_doc/1
{
  "name":"张三",
  "age":18,
  "sex":"男"
}

添加文档,不指定id
POST person/_doc
{
  "name":"翠花",
  "age":20,
  "sex":"女"
}

删除文档
DELETE person/_doc/1
# ==========文档的操作=============

# 指定id添加文档

POST person/_doc/1
{
  "name":"如花",
  "age": 18,
  "sex":"男"
}

# 不指定id添加文档
POST person/_doc/2
{
  "name":"翠花",
  "age": 19,
  "sex":"女"
}

# 查看所有文档
GET person/_search

# 根据id查看文档
GET person/_doc/rdJ9qYIB33sH7ezNb5Mu

# 修改文档
PUT person/_doc/rdJ9qYIB33sH7ezNb5Mu
{
  "name":"玫瑰花",
  "age":"20"
}

# 根据id删除文档
DELETE person/_doc/rdJ9qYIB33sH7ezNb5Mu

#注: 添加文档不指定id会自动生成一个id值

分词器

  • Standard Analyzer - 默认分词器,按词/字切分,小写处理 (英文)

  • Simple Analyzer - 按照非字母切分(符号被过滤),小写处理

  • Stop Analyzer - 小写处理,停用词过滤(the,a,is)

  • Whitespace Analyzer - 按照空格切分,不转小写

  • Keyword Analyzer - 不分词,直接将输入当作输出

  • Patter Analyzer - 正则表达式,默认\W+(非字符分割) (中文会被去掉)

  • Language - 提供了30多种常见语言的分词器

第三方ik 分词器

ik_smart:最小分词法

ik_max_word:最细分词法

Elasticsearch高级搜索:查询接口说明

查询所有:查询出所有数据,一般测试用。例如:match_all

全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:

  • multi_match_query

  • match_query

精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:

  • ids
  • range
  • term

地理(geo)查询:根据经纬度查询。例如:

  • geo_distance
  • geo_bounding_box

复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:

  • bool
  • function_score

常见的全文检索查询包括:

match查询:单字段查询

multi_match查询:多字段查询,任意一个字段符合条件就算符合查询条件

match查询语法如下:

GET /indexName/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  }
}

mulit_match语法如下:

GET /indexName/_search
{
  "query": {
    "multi_match": {
      "query": "TEXT",
      "fields": ["FIELD1", " FIELD12"]
    }
  }
}

精准查询

  • term:根据词条精确值查询(针对非数值类型)

  • range:根据值的范围查询(针对数值类型)

# 精确检索
# 需求:查询上海的酒店
GET hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}

# 需求:查询五星级的酒店
GET hotel/_search
{
  "query": {
    "term": {
      "starName": {
        "value": "五星级"
      }
    }
  }
}

# 需求:查询价格500-100的酒店
GET hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 500,
        "lte": 1000
      }
    }
  }
}

地理坐标查询

矩形范围查询,也就是geo_bounding_box查询,查询坐标落在某个矩形范围的所有文档:

附近查询,也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。

# 矩形位置检索
GET hotel/_search
{
  "query": {
    "geo_bounding_box":{
      "location":{
        "top_left":{
          "lat": 31.1,
          "lon": 121.5
        },
        "bottom_right":{
          "lat": 30.9,
          "lon": 121.7
        }
      }
    }
  }
}

# 距离位置检索(圆形位置检索)
GET hotel/_search
{
  "query": {
    "geo_distance":{
      "location":"31.1,121.5",
      "distance": "10km"
    }
  }
}

复合查询-算分函数查询

使用场景

当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。

elasticsearch会根据词条和文档的相关度做打分,算法由两种:

  • TF-IDF算法

  • BM25算法,elasticsearch5.1版本后采用的算法

function score 查询中包含四部分内容:

  • 原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)

  • 过滤条件:filter部分,符合该条件的文档才会重新算分

  • 算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数

    • weight:函数结果是常量

    • field_value_factor:以文档中的某个字段值作为函数结果

    • random_score:以随机数作为函数结果

    • script_score:自定义算分函数算法

  • 运算模式:算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:

    • multiply:相乘

    • replace:用function score替换query score

    • 其它,例如:sum、avg、max、min

function score的运行流程如下:

  • 1)根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)

  • 2)根据过滤条件,过滤文档

  • 3)符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)

  • 4)将原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分。

因此,其中的关键点是:

  • 过滤条件:决定哪些文档的算分被修改

  • 算分函数:决定函数算分的算法

  • 运算模式:决定最终算分结果

# 复合查询-分值函数查询

# 优先显示"北京"地区的 "如家"酒店

GET hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "all": "如家"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "city": "北京"
            }
          },
          "weight": 20
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

复合查询-布尔查询

使用场景

布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:

  • must:必须匹配每个子查询,类似“与”

  • should:选择性匹配子查询,类似“或”

  • must_not:必须不匹配,不参与算分,类似“非”

  • filter:必须匹配,不参与算分

# 复合查询- 布尔查询

# 搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店

GET hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "all": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": {
        "geo_distance": {
          "distance": "10km",
          "location": "31.21,121.5"
        }
      }
    }
  }
}

lasticsearch高级搜索:搜索结果处理

普通字段排序

keyword、数值、日期类型排序的语法基本一致。

DSL语法

排序条件是一个数组,也就是可以写多个排序条件。按照声明的顺序,当第一个条件相等时,再按照第二个条件排序,以此类推

# 普通字段排序

# 需求:对“如家”酒店价格进行倒序排序

GET hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  }, 
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}

# 地理位置排序

# 需求:我的坐标是31.034661,121.612282,寻找我周围距离最近的酒店(由近到远)

GET hotel/_search
{
  "sort": [
    {
      "_geo_distance": {
        "location": "31.034661,121.612282",
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

分页

elasticsearch 默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了。elasticsearch中通过修改from、size参数来控制要返回的分页结果:

  • from:从第几个文档开始,从0开始的

  • size:总共查询几个文档

# 结果分页

# 需求:查询第1页,每页显示20条
# from值算法=(页码-1)* size

GET hotel/_search
{
  "query": {
    "match": {
      "all": "虹桥如家"
    }
  },
  "from": 20,
  "size": 20
}

高亮显示

高亮显示的实现分为两步:

  • 1)给文档中的所有关键字都添加一个标签,例如<em>标签

  • 2)页面给<em>标签编写CSS样式

# 高亮显示

# 对name字段内容进行高亮

# 高亮属性配置
# require_field_match: 该高亮字段是否必须参与搜索条件,true:必须参数(默认值),false: 可以不参与

# pre_tags和post_tags:修改高亮样式,默认<em></em>

GET hotel/_search
{
  "query": {
    "match": {
      "all": "虹桥如家"
    }
  },
  "highlight": {
    "fields": {// 指定要高亮的字段
      "name": {
        "require_field_match": "false"
      }
    },
    "pre_tags": "<font color='red'>",// 用来标记高亮字段的前置标签
    "post_tags": "</font>"// 用来标记高亮字段的后置标签
  }
}

Elasticsearch聚合搜索:聚合分类

聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组 类似mysql的group by

    • TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组

    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

  • 类似于mysql统计函数 count,sum,max,min,avg

    • Avg:求平均值

    • Max:求最大值

    • Min:求最小值

    • Stats:同时求max、min、avg、sum等

  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

Bucket聚合

根据这个需求,其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合,也就是Bucket聚合。

GET /hotel/_search
{
  "size": 0,  // 设置size为0,结果中不包含文档,只包含聚合结果
  "aggs": { // 定义聚合
    "brandAgg": { //给聚合起个名字
      "terms": { // 聚合的类型,按照品牌值聚合,所以选择term
        "field": "brand", // 参与聚合的字段
        "size": 20 // 希望获取的聚合结果数量
      }
    }
  }
}

聚合结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为count,并且按照count降序排序。

我们可以指定order属性,自定义聚合的排序方式:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "order": {
          "_count": "asc" // 按照_count升序排列
        },
        "size": 20
      }
    }
  }
}

限定聚合范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。

我们可以限定要聚合的文档范围,只要添加query条件即可:

# 注意:通常在做聚合查询时,可以设置size=0,为了取消查询列表数据
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 200 // 只对200元以下的文档聚合
      }
    }
  }, 
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

Metric聚合

这就要用到Metric聚合了,例如stat聚合:就可以获取min、max、avg等结果。

语法如下:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": { 
      "terms": { 
        "field": "brand", 
        "size": 20
      },
      "aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算
        "score_stats": { // 聚合名称
          "stats": { // 聚合类型,这里stats可以计算min、max、avg等
            "field": "score" // 聚合字段,这里是score
          }
        }
      }
    }
  }
}

过滤条件聚合显示

搜索页面的品牌、城市等信息不应该是在页面写死,而是通过聚合索引库中的酒店数据得来的:

# 统计酒店的品牌,星级,城市

GET hotel/_search
{ 
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "all": "酒店"
          }
        }
      ],
      "filter": [
           {
              "term": {
                "city": "上海"
              }
           } ,
           {
              "term": {
                "brand": "如家"
              }
           } ,
           {
              "term": {
                "starName": "二钻"
              }
           },
           {
             "range": {
                "price": {
                  "gte": 100,
                  "lte": 200
                }
              }
           }
        
      ]
    }
  },
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 100
      }
    },
    "starAgg": {
      "terms": {
        "field": "starName",
        "size": 100
      }
    },
    "cityAgg": {
      "terms": {
        "field": "city",
        "size": 100
      }
    }
  }
}

自定义分词器

默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。

elasticsearch中分词器(analyzer)的组成包含三部分:

  • character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符

  • tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart

  • tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

声明自定义分词器的语法如下:

PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": { // 自定义分词器
        "my_analyzer": {  // 分词器名称
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": { // 自定义tokenizer filter
        "py": { // 过滤器名称
          "type": "pinyin", // 过滤器类型,这里是pinyin
		  "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "ik_max_word"
      }
    }
  }
}

结合以上的DSL,拼音分词,自定义分词, 自动补全,建立索引库

PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_anlyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_max_word",
        "copy_to": "all"
      },
      "address":{
        "type": "keyword",
        "index": false
      },
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      "brand":{
        "type": "keyword",
        "copy_to": "all"
      },
      "city":{
        "type": "keyword"
      },
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword",
        "copy_to": "all"
      },
      "location":{
        "type": "geo_point"
      },
      "pic":{
        "type": "keyword",
        "index": false
      },
      "all":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_max_word"
      },
	  "suggestion":{
        "type": "completion",
        "analyzer": "text_anlyzer",
		"search_analyzer": "ik_max_word"
      }
    }
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值