关于 ElasticSearch 的安装配置请查阅这篇文章:https://blog.csdn.net/weixin_43941364/article/details/105680161
IK 分词器的使用
最少拆分ik_smart
:
GET _analyze
{
"analyzer": "ik_smart",
"text": "中国是一个伟大的国家"
}
结果是:
{
"tokens" : [
{
"token" : "中",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "国是",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "一个",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "伟大",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "的",
"start_offset" : 7,
"end_offset" : 8,
"type" : "CN_CHAR",
"position" : 4
},
{
"token" : "国家",
"start_offset" : 8,
"end_offset" : 10,
"type" : "CN_WORD",
"position" : 5
}
]
}
最细粒度拆分ik_max_word
:
GET _analyze
{
"analyzer": "ik_max_word",
"text": "中国共产党"
}
查询结果:
{
"tokens" : [
{
"token" : "中国共产党",
"start_offset" : 0,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "中国",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "国共",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "共产党",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "共产",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "党",
"start_offset" : 4,
"end_offset" : 5,
"type" : "CN_CHAR",
"position" : 5
}
]
}
那么这些分词的依据是什么呢?
我们可以点开 ik 分词器的 config
目录查看一下字典:
其中这些 dic
就是我们的字典。
在这里可以自定义自己的词典:
要注意的是每次修改完配置项之后都要重启服务。
在 ElasticSearch 中 索引
相当于 数据库,type
相当于表, document
相当于一行记录,Field
相当于属性名。
PUT /test1/type1/1
{
"name": "硕子鸽",
"age": 18
}
执行成功,即可查看:
我们再来了解一下数据类型,这里参考官方文档 https://www.elastic.co/guide/en/elasticsearch/reference/7.7/mapping-types.html
指定字段的类型,我们只创建一个数据库索引,为他指定字段的名称和类型,即创建规则:
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "long"
},
"birthday": {
"type": "date"
}
}
}
}
创建成功看一下:
查询命令使用 GET
如果我们不指定字段类型呢?
在版本 7.6 及其以上版本,我们使用索引名 + _doc 创建一条记录,/test3/_doc/1
,如果不指定则默认就是 _doc
。
也就是说 Elasticsearch 会自动识别我们的字段,然后设置合适的字段类型。
注意:keyword
为不可分割类型。
我们可以使用命令:GET _cat/indices?v
查看默认配置信息。
直接使用添加数据的方法,他会覆盖原来的数据,然后在原来的版本号上 +1
.
这个方法有个弊端,就是如果你漏掉了一个数据,那么这个数据就没了,要想修改一个数据,必须把原来的都带上很麻烦,我们来看一下新的方法。
使用 POST 命令:
POST /test3/_doc/1/_upodate
{
"doc": {
"name": "硕子弟"
}
}
删除索引:
DELETE test1
通过 DELETE 命令,根据你的命令判断,如果后面还有下一级,则会只删除下一级的数据。
使用 PUT
请求,输入demo/user/1
,插入一条数据:
{
"name": "张三",
"age": 30,
"desc": "这是一号同学的描述",
"tags": [
"标签1",
"标签2",
"标签3"
]
}
然后插入第二条数据 demo/user/2
:
{
"name": "李四",
"age": 29,
"desc": "这是二号同学的描述",
"tags": [
"标签1",
"标签2",
"标签3"
]
}
第三条 demo/user/3
:
{
"name": "王五",
"age": 28,
"desc": "这是三号同学的描述",
"tags": [
"标签1",
"标签2",
"标签3"
]
}
如果要查询的话,发送 GET 请求,就是简单的条件查询:
demo/user/1
这是最简单的根据 ID 查询,那稍微复杂一点的查询呢?
demo/user/_search?q=name:张三
如果使用这个:
demo/user/_search?q=desc:同学
他会把所有的描述信息带有同学的记录都查询出来,这个时候就体现出来搜索了。
可以看到上面的返回数据中有一个 score
字段,这个字段的含义就是权重的意思。
我们也可以使用下面的这个查询:
demo/user/_search GET
{
"query": {
"match": {
"name": "李四"
}
}
}
也会得到相同的结果。
我们使用 Kibana 来操作一下:
首先创建数据:
PUT /test2/_doc/1
{
"name": "张三",
"age": 18,
"desc": "像一个菜鸡",
"tags": [
"憨批", "菜鸡", "蒟蒻"
]
}
PUT /test2/_doc/2
{
"name": "李四",
"age": 19,
"desc": "像2个菜鸡",
"tags": [
"憨批1", "菜鸡1", "蒟蒻1"
]
}
PUT /test2/_doc/3
{
"name": "王五",
"age": 20,
"desc": "像3个菜鸡",
"tags": [
"憨批2", "菜鸡2", "蒟蒻2"
]
}
然后修改数据:
POST /test2/_doc/1/_update
{
"doc": {
"desc": "菜鸡可不是我"
}
}
POST /test2/_doc/3/_update
{
"doc": {
"desc": "我是猪"
}
}
然后查询数据:
GET test2/_search?q=name:张三;
GET test2/_search?q=desc:猪;
get test2/_search
{
"query": {
"match": {
"name": "张三"
}
}
}
返回结果为:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.0996442,
"hits" : [
{
"_index" : "test2",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.0996442,
"_source" : {
"name" : "张三",
"age" : 18,
"desc" : "菜鸡可不是我",
"tags" : [
"憨批",
"菜鸡",
"蒟蒻"
]
}
}
]
}
}
hits
:索引和文档信息,查询出来的是具体的文档;_score
:通过分数来判断最佳匹配;只想要指定的字段:
GET test2/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name", "desc"]
}
只查出 name 和 sesc;
"hits" : [
{
"_index" : "test2",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.6533571,
"_source" : {
"name" : "张三",
"desc" : "菜鸡可不是我"
}
}
]
排序
使用 sort
:
GET test2/_search
{
"query": {
"match": {
"desc": "菜鸡"
}
},
"sort": [
{
"age": {
"order": "asc"
}
}
]
}
分页
from
:从第几个数据开始;size
:每页的个数;GET test2/_search
{
"query": {
"match": {
"desc": "菜鸡"
}
},
"sort": [
{
"age": {
"order": "asc"
}
}
],
"from": 0,
"size": 2
}
返回布尔值
GET test2/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"
}
},
{
"match": {
"age": "18"
}
}
]
}
}
}
must
:所有的条件都要符合;shoulder
:两个条件满足其一就行。must_not
:结果取反;过滤器
GET test2/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"
}
}
],
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
filter
:过滤选项;gte
:大于等于;lte
:小于等于;gt
:大于;lt
:小于。匹配多个条件
直接使用空格隔开:
GET test2/_search
{
"query": {
"match": {
"tags": "菜鸡 憨批"
}
}
}
精确查询
term
:直接查询精确的;match
:会使用分词器,先分析文档,然后在通过分析文档进行查询;两个类型
text
:会被分词器解析;keyword
:不会被分词器解析;严格的查询年龄是 18 岁的人:
GET test2/_search
{
"query": {
"term": {
"age": 18
}
}
}
高亮查询
GET test2/_search
{
"query": {
"match": {
"name": "张三"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
查询结果:
"hits" : [
{
"_index" : "test2",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.6533571,
"_source" : {
"name" : "张三",
"age" : 18,
"desc" : "菜鸡可不是我",
"tags" : [
"憨批",
"菜鸡",
"蒟蒻"
]
},
"highlight" : {
"name" : [
"<em>张</em><em>三</em>"
]
}
}
]