Published on

Elasticsearch 基础入门:核心概念、查询与索引模板解析

Authors
  • avatar
    Name
    Liant
    Twitter

搜索部分

该部分介绍:ES最最基本的知识.ES是个什么,能干什么,最简单的使用.

内容:介绍基本查询,和mapping的的作用以及使用

返回结果

{
    "took": 0, // 花费时间
    "timed_out": false,
    "_shards": { // 各分片执行情况
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3214, // 匹配的文档数
            "relation": "eq" // ver7以后不在默认总的匹配量,
        },
        "max_score": 1.0, // 结果中最高的评分
        "hits": [ // 结果集
            {
                "_index": "area_index001", // 索引
                "_type": "_doc", // type,默认都是_doc.不在推荐使用其他的
                "_id": "617b6749e95b0000560061e2", // 文档ID
                "_score": 1.0, // 相关度评分,可以排序等
                "_source": { // 原始文档
                    "area_desc_id": "1",
                    "area_sub": [
                        {
                            "_id": "617b67e9e95b0000560061e4",
                            "code": "110101",
                            "id": "2",
                            "name": "东城区",
                            "pcode": "110100",
                            "pid": "1",
                            "zipcode": "100000"
                        },
                        {}
                    ]
                }
            }
        ]
    }
}

HTTP 查询接口

几种书写形式

  • /_search 所有索引
  • /index001/_search 指定索引
  • /index001,index002/_search 多个索引
  • /index*/_search 通配符匹配索引
curl -XGET "http://es01:9200/index001/_search?q=content:练习&df=title&sort=year:desc&from=0&size=10&timeout=1s"-d \
-H 'Content-Type: application/json' \
'{
    "profile":true
}'
q 指定查询语句,使用query string syntax
df 默认字段,不指定时,会对所有字段进行查询
sort,from,size 用于分页
timeout 超时
profile 返回profile块,查看执行过程.可以用于优化查询

泛查询:对_all,所有字段查询

query string syntax
  • 指定字段查询 与 泛查询
q=title:aaa / q=aaa
  • term(准确) 与 phrase(短语)
Beautiful Mind 等效于 Beautiful OR Mind  
"Beautiful Mind" 等效于 Beautiful AND Mind,phrase 要求顺序保持一致  
  • 分组 与 引号
title:(Beautiful AND Mind)  
title:"Beautiful Mind"  
  • 布尔操作
AND/OR/NOT 或则 &&/||/!  
 必须大写;title:(matrix NOT reloaded)
  • 分组
`+` 表示must,`-` 表示must_not  
title:(+matrix -reloaded)  
URL中需要转义 + => %2B,
  • 范围查询
[]表示闭区间,{}表示开区间
year:{2010 TO 2018}
year:{* TO 2018}
  • 算数符号
year:>2000  
year:(>2000 && <=2018)  
year:(+>2000 +<=2018)  
  • 通配符
?代表一个字符,*代表0个或多个字符  
title:mi?d  
title:be*
  • 正则表达式
title:[bt]oy
  • 模糊匹配与近似查询
title:befutifl~1
title:"lord rings"~2 (~2可以间隔连个词)
curl -XPOST '192.168.50.111:9200/custom_news/_search' \
-H 'Content-Type: application/json' \
-d '{
    "sort":[
        {"order_date":"desc", "_score":"desc"}
    ],
    "source":["order_date", "order_time", "category"]
    "size":10,
    "from":20,
    "query": {
        "match_all": {}
    }
}'
  • size,from 分页

  • source 需要的字段

  • script_fields

{
    "script_fields":{
        "new_field":{
            "script":{
                "lang":"painless",
                "source":"doc['order_date'].value+'_hello'"
            }
        }
    },
    "query":{
        "match_all":{}
    }
}
  • match 查询表达式
{
    "query":{
        "match":{ // default or
            "common":"last day"
        }
    }
}
{
    "query":{
        "match":{
            "common":{
                "query":"last day",
                "operator":"AND"
            }
        }
    }
}
  • match_phrase 短语查询
{
    "query":{
        "match_phrase":{
            "common": {
                "query":"song lost Chrismas",
                "slop":1
            }
        }
    }
}

需要单词顺序出现,slop为单词中间可以间隔几个其他字符

  • query_string
{
    "query":{
        "query_string":{
            "default_field":"",
            "query":"(zhang AND san) OR (li AND si)"
        }
    }
}
  • simple_query_string query不支持词 AND OR NOT逻辑词,使用+|-
{
    "query":{
        "simple_query_string":{
            "query":"zhang -san"
            "fields": ["name"],
            "default_operator":"AND",
        }
    }
}

mapping

数据库中的schema,表结构定义.包括表名,字段类型.指定分词器等.

字段类型

简单类型

  • text/keyword
  • date
  • integer / floating
  • boolean
  • ipv4 & ipv6

复杂类型

  • 对象类型/嵌套类型

特殊类型

  • geo_point & geo_shape/percolator

Dynamic Mappping(动态映射),向Elasticsearch写入文档时,索引不存在就会自动创建索引. Elasticsearch会根据mapping指定的字段类型,以相应的字段格式存储,可以正常查询.

类型自动识别

JSON类型Elasticsearch类型
字符串text,Date,等
布尔值Boolean
浮点数float
整数long
对象Object
数组由第一个非空数值的类型所决定
空值忽略

对于mapping的更改,值为字符串

  • 新增字段
    • Dynamic=true时,一旦有新文档写入,mapping也会同时更新
    • Dynamic=false时,mapping不会被更新,不能被索引.只会出现在_source中
    • Dynamic=strict,文档写入失败
  • 已有字段
    • 不支持修改字段类型,要修改只能重建索引
-truefalsestrict
文档可索引YESYESNO
字段可索引YESNONO
mapping被更新YESNONO
PUT demo
{
    "mappings":{
        "_doc":{
            "dynamic":"false"
        }
    }
}

显示定义mapping

  • index:false 文档字段不被索引
{
    "mappings":{
        "properties":{
            "firstName": {
                "type":"text"
            },
            "lastName": {
                "type":"text"
            },
            "mobile": {
                "type":"keyword",
                "index":false
            }
        }
    }
}
  • null_value null值默认是忽略.

只有keyword支持null_value

GET /users/_search?q=mobile:NULL
{
    "mappings":{
        "properties":{
            "firstName": {
                "type":"text"
            },
            "lastName": {
                "type":"text"
            },
            "mobile": {
                "type":"keyword",
                "null_value":"NULL"
            }
        }
    }
}
{
    "_source":{
        "firstName":"zhang"
        "lastName":"san"
        "mobile": null
    }
}
  • copy_to, 不会出现在_source中
GET /users/_search?q=fullName:(zhang san)
{
    "mappings":{
        "properties":{
            "firstName": {
                "type":"text",
                "copy_to":"fullName"
            },
            "lastName": {
                "type":"text",
                "copy_to":"fullName"
            }
        }
    }
}
  • 数组 都可以索引成功,所以字段值本身就可以是一个数组
PUT /user/_doc/1
{
    "name":"zhangsan",
    "interests":"reading"
}
PUT /user/_doc/1
{
    "name":"zhangsan",
    "interests":["reading", "music"]
}

多字段类型

PUT users
{
    "mappings":{
        "properties":{
            "company": {
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "comment": {
                "type":"text",
                "fields":{
                    "english_comment":{
                        "type":"text",
                        "analyzer":"english",
                        "search_analyzer":"english"
                    }
                }
            }
        }
    }
}
GET /users/_search
{
    "query":{
        "match":{
            "company.keyword":"公司名称"
        }
    }
}
  • exact Values(精确值) 和 Full text(文本值) 只有文本值需要做分词,通过搜索关键字来匹配内容

mapping的分词器

已有分词器

  • 内部分词器
Simple Analyzer – 按照非字母切分(符号被过滤),小写处理
Stop Analyzer – 小写处理,停用词过滤(the,a,is)
Whitespace Analyzer – 按照空格切分,不转小写
Keyword Analyzer – 不分词,直接将输入当作输出
Patter Analyzer – 正则表达式,默认 \W+ (非字符分隔)
Language – 提供了30多种常见语言的分词器
  • 第三方分词器

中文分词器

  • ik GitHub开源的
  • thulac 中文分词器,清华的
  • 查看分词器的效果
#standard
GET _analyze
{
  "analyzer": "standard",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

POST _analyze
{
  "analyzer": "standard",
  "text": "他说的确实在理”"
}

自定义分词器

包含三部分, Character filter,Tokenizer,Token Filter

Character filter

在Tokenizer之前处理,例如删除以及替换字符.可以配置多个Character filter.会影响Tokenizer的position和offset信息

一些自带的Character filter:

  • HTML strip - 去处HTML标签
  • Mapping - 字符串替换,支持表情符号.(字符转移)
  • Pattern replace - 正则匹配替换

示例:

去掉html标签

POST _analyze
{
    "tokenizer":"keyword",
    "char_filter":["html_strip"],
    "text":"<h1>Hello word</h1>"
}

替换 -_,表情替换

POST _analyze
{
    "tokenizer":"standard",
    "char_filter":[
        {
            "type":"mapping",
            "mappings":[
                "- => _",
                ":) => happy",
                ":( => sad"
                ]
        }
    ],
    "text":"123-456,test-acb"
}

正则

POST _analyze
{
    "tokenizer":"standard",
    "char_filter":[
        {
            "type":"pattern_replace",
            "pattern":"http://(.*)",
            "replacement":"$1"
        }
    ],
    "text":"http://www.elastic.co"
}
Tokenizer

将原始文本按照一定规则,切分成term或者token(这些term或者token就是检索的最小匹配单元).
一些自带的Tokenizer:

  • whitespace
  • standard
  • uax_url_email
  • pattern
  • keyword
  • path hierarchy 处理文件路径分词

可以使用Java插件开发自己的Tokenizer,像ik分词器

示例: stop:停止词, the 等

POST _analyze
{
    "tokenizer":"whitespace",
    "filter":["lowercase", "stop"]
    "text":"http://www.elastic.co"
}
Token Filter

Tokenizer的结果进行处理,修改删除等

一些自带的Token Filter:

  • lowercase 小写
  • stop
  • synonym 添加近义词,针对英文
示例
PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "char_filter": [
            "emoticons" // 自定义
          ],
          "tokenizer": "punctuation", // 自定义
          "filter": [
            "lowercase",
            "english_stop" // 自定义
          ]
        }
      },
      "tokenizer": {
        "punctuation": {//正则
          "type": "pattern",
          "pattern": "[.,!?]"
        }
      },
      "char_filter": {
        "emoticons": { // 表情替换
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": {
        "english_stop": { // 分隔符
          "type": "stop",
          "stopword": "_english_"
        }
      }
    }
  }
}
POST /my_index/analyzer
{
    "analyzer":"my_custom_analyzer",
    "text":"I'm a :) person, and you ?"
}

index template 和 dynamic template

index template

预先设定mapping和setting,按照一定规则,自动匹配到新创建的索引之上

  • 模板仅在一个索引被新创建时有效,修改模板不会影响已有的索引

  • 可以设置多个索引模板,这些索引会被合并

  • 指定 order值,控制合并的过程

PUT /_template/template_test_001
{
  "index_patterns":["*"],
  "order": 0,
  "version":1,
  "settings":{
    "number_of_shards":1,
    "number_of_replicas":1
  }
}

工作顺序

  • 应用默认的 settingsmappings
  • order 低的
  • order 高的,覆盖之前的值
  • 创建index时,settingsmappings覆盖template的值

dynamic template

适用于具体的index,动态设定字段类型

  • 所有的字符串类型都设定成keyword,或者关闭keyword
  • is开头的字段都设置成bool
  • bool_开头的都设置成long

示例

PUT my_test_index
{
  "mappings": {
    "dynamic_template": [
      {
        "string_as_boolean": {
          "match_mapping_type": "string",
          "match": "is*",
          "mapping": {
            "type": "boolean"
          }
        }
      },
      {
        "string_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

参考资料

极客时间-ES文档