写在前面
本文记录es的零碎知识点,包括但不限于概念,集群方式,等。
1:词项查询 VS 全文查询
词项查询:查询的内容不做分词处理,输入的什么查询什么。
全文查询:查询的内容会做分词处理,生成多个词项,然后对每个词项分别查询,所有的查询结果汇总在一起,作为最终的结果。
具体参考这里 。
2:Query Context VS Filter Context
Query Context:算分的上下文。
Filter Context:不算分的上下文。
3:copy_to
使用copy_to,如下:
测试:
# 1:先删除索引,因为前面创建过了
DELETE users
# 2:创建索引,并指定firstName的null_value
PUT users
{
"mappings": {
"properties": {
"firstName": {
"type": "text",
"copy_to": "fullName"
},
"lastName": {
"type": "text",
"copy_to": "fullName"
}
}
}
}
# 3:创建新数据
POST users/_create/1
{
"firstName": "jack",
"lastName": "james"
}
# 4:搜索在fulleName中包含jack或者是包含james的,可以正常搜索到
GET users/_search?q=fullName:(jack james)
{
"profile": "true"
}
4:常见分词器
4.1:中文分词器
ik 。
icu 。
pinyin 分词为拼音
配置:
例子:
- HanLP
安装参考pinyin ,下载参考下图:
5:相关性,相关文档,precision,recall
- 相关性
1:需要找到的文档都找到了?
2:找到了多少错误的文档??
3:找到的文档评分高低是否符合预期???
- 相关文档
应该找到的文档。 - precision,recall
如果找到的文档我们标记为positive
,没有找到的文档标记为negative
,然后我们用true
来表示找到的该找到的,没找到的不该找到的,用false来表示没找到的该找到的,找到的不该找到的绕啊!!!
,则我们可以得到下图:
precision就是:返回的文档中相关文档数/返回的文档数
recall就是:返回的相关文档/总相关文档
如下图:
一般搜索时尽量提高recall值是我们的目标。
详细参考Elasticsearch:理解搜索中的 precision 及 recall 。
6:使用_analyze API查看分词效果
POST _analyze
{
"analyzer": "standard",
"text": "Michael Jordan agrees to help the Looney Tunes play a basketball game against aliens slavers to determine their freedom"
}
7:多字段类型
考虑这样的场景,对于文档的某个字段,有时候我们需要对其进行模糊查询,有时候需要对其进行精确查询,此时,就可以考虑使用多字段类型,即给字段设置一个子字段,当然,在当前假设的场景下,子字段的类型需要设置为keyword
,来满足精确查找的需求,如下:
# 1:先删除索引,因为前面创建过了
DELETE users
# 2:创建索引,并指定firstName的null_value
PUT users
{
"mappings": {
"properties": {
"firstName": {
"type": "text",
"fields": {
"my_keyword": {
"type": "keyword"
}
}
},
"lastName": {
"type": "text"
}
}
}
}
# 3:插入数据
POST users/_create/1
{
"firstName": "AA BB CC",
"lastName": "james"
}
# 4:使用firstName查询“AA BB”可以查询到,此时是模糊匹配
GET users/_search?q=firstName:"AA BB"
{
"profile": "true"
}
# 5:使用firstName的子字段my_keyword查询“AA BB”查询不到,因为是精准匹配
GET users/_search?q=firstName.my_keyword:"AA BB"
{
"profile": "true"
}
# 6:使用firstName的子字段my_keyword查询“AA BB CC"可以查询到
GET users/_search?q=firstName.my_keyword:"AA BB CC"
{
"profile": "true"
}
注意keyword和text的关键区别就是,keyword是精确匹配,text是模糊匹配。当然text当给定的是完全匹配的值时也是可以查询到的,但本质上还是通过模糊查询的方式匹配到的,这点要注意。
当然我们也可以设置一个指定了自定义分词器的子字段,如下:
具体的可以根据业务场景来灵活定义。
8:doc_values和fielddata
一般地,我们在使用es进行搜索时,使用的数据结构是倒排索引 ,但是当我们执行诸如order by排序,sum聚合等操作时,这种数据结构就无能为力了,所以es就引入了doc_values和field_data这两种数据结构,其中fielddata是1.x版本以及之前提供的数据结构,这种数据结构基于内存来实现,所以可能会给jvm heap带来比较大的压力,数据量比较大时可能发生OOM,所以在2.x版本开始引入了doc values,这是一种基于磁盘的数据结构,因为基于磁盘,所以性能肯定不及fielddata,但随着磁盘技术本身的发展(SSD)
以及doc value程序本身的不断优化,性能差异也越来越小了,所以目前官方大力发展的就是doc value了,具体二者比较参考下图:
详细参考一文带你彻底弄懂ES中的doc_values和fielddata 。
9:排序 sort _doc
_doc
排序就是按照文档的索引顺序,即插入到分片的先后顺序,来排序获取,如下:
注意以下测试分片数是1,所以顺序是和肉眼看到的一致的,但是多个分片就不一定了,因为是插入分片的顺序,而非插入到es的顺序。
- 准备数据
DELETE message
PUT message
{
"settings": {
"number_of_shards": 1
}
}
POST message/_doc?routing=1
{
"content": "good"
}
POST message/_doc?routing=2
{
"content": "good morning"
}
POST message/_doc?routing=3
{
"content": "good morning everyone"
}
- 按照插入的顺序返回
POST message/_search
{
"size": 5,
"query": {
"match_all": {}
},
"sort": [
{
"_doc": {
"order": "asc"
}
}
]
}
- 按照插入相反的顺序返回
POST message/_search
{
"size": 5,
"query": {
"match_all": {}
},
"sort": [
{
"_doc": {
"order": "desc"
}
}
]
}
10:批量插入bulk
POST news/_bulk
{"index": {"_id": 1}}
{"f1":"aa", "f2": "bb"}
{"index": {"_id": 2}}
{"f1":"aa", "f2": "bb", "f3": "cc"}
{"index": {"_id": 3}}
{"f1":"aa", "f2": "bb", "f3": "cc", "f4": "dd"}
11:source filtering
默认在我们查询文档时,最初生成该文档的_source信息也会一并返回,我们可以通过source filtering的功能来控制不返回_source,或者是只返回部分字段,如下准备测试数据:
DELETE test_source_filtering
PUT test_source_filtering/_doc/1
{
"title": "Mastering ElasticSearch 5.0",
"description": "Master the searching, indexing, and aggregation features in ElasticSearch Improve users’ search experience with Elasticsearch’s functionalities and develop your own Elasticsearch plugins",
"author": "Bharvi Dixit",
"public_date": "2017",
"cover_url": "https://images-na.ssl-images-amazon.com/images/I/51OeaMFxcML.jpg"
}
查询会返回完整的_source:
POST test_source_filtering/_search
{
"query": {
"match_all": {}
}
}
控制不返回_source:
# 不返回_source
POST test_source_filtering/_search
{
"_source": false,
"query": {
"match_all": {}
}
}
是只返回部分字段:
# _source中返回个别字段
POST test_source_filtering/_search
{
"_source": ["title","author"],
"query": {
"match_all": {}
}
}
# _source中指定包含的字段和删除的字段
POST test_source_filtering/_search
{
"_source": {
"includes": ["tit*","cover_url"],
"excludes": ["author"]
},
"query": {
"match_all": {}
}
}
参考的Elastic Search之Source Filtering(过滤结果中"_source"原始文本显示哪些字段) 。