DSL 搜索
ES 使用 queryString 形式根据搜索词对索引表的文档进行检索:
GET /{indexName}/_doc/_search?q={fieldName1}:{searchTxt1}&q={fieldName2}:{searchTxt2}..
但这种 queryString 的形式查询数据只适合一些简单查询的场景,一旦参数多了就难以进行构建(需要添加分页、过滤等功能),所以多数情况下使用 DSL Domain Specific Language 进行查询更好,因为它基于 JSON 格式的数据查询,这样的可读性会更好,有利于复杂查询。
1 DSL 语法
1.1 基本搜索
match_all关键字,表示 在索引中查询所有文档(上一篇文章有queryString查询的做法)_source关键字填充需要搜索的字段名from和size:默认的 ES 只显示10条数据,此时可以使用分页显示,from是表示从起始索引,size表示一页显示的个数
POST /{indexName}/_doc/_search
{
"query": {
"match_all": {}
},
"_source": [{fieldName1}, {fieldName2}...],
"from": 1,
"size": 5
}
match关键字,将 搜索内容进行分词后搜索match关键字默认的operator属性是or,即搜索内容分词后,只要存在一个词语匹配就展示结果,设置为and后,搜索内容分词后,都要满足词语匹配minimum_should_match:最低匹配精度,比如说最低匹配精度为70%,而搜索内容分词后有10个词语,则文档必须要有10*0.7=7个词语匹配才会符合显示需求。
POST /{indexName}/_doc/_search
// 默认 operator 为 or
{
"query": {
"match": {
{fieldName}: {searchTxt}
}
}
}
// 设置 operator 为 true
{
"query": {
"match": {
{fieldName}: {
"query": {searchTxt},
"operator": "and"
}
}
}
}
// 最低匹配精度
{
"query": {
"match": {
{fieldName}: {
"query": {searchTxt},
"minimum_should_match": {minimum_should_match}
}
}
}
}
multi_match关键字,满足使用match模式在多个字段属性中进行查询的需求boost权重,多字段属性查询时,可为某些字段属性设置权重,权重越高,文档相关性得分就越高,如下{fieldName2}^{weight}举例:"desc^10"表示desc字段属性搜素提升10倍相关性,即如果其他字段没有设置权重,用户搜索时会以desc为主
POST /{indexName}/_doc/_search
{
"query": {
"multi_match": {
"query": {searchTxt},
"fields": [{fieldName1}, {fieldName2}...]
}
}
}
// 设置权重
{
"query": {
"multi_match": {
"query": {searchTxt},
"fields": [{fieldName1}, {fieldName2}^{weight}...]
}
}
}
match_phrase关键字,搜索内容的分词结果必须在文档分词中都包含,且顺序必须相同,而且必须连续(词与词之间必须紧贴在一起),除非设置了slop属性,允许词语之间跳过的文字数量
POST /{indexName}/_doc/_search
{
"query": {
"match_phrase": {
"desc": {
"query": {searchTxt},
"slop": {slopNum}
}
}
}
}
term关键字与terms关键字,将 搜索内容作为一整个关键词去搜索,而不是进行分词后搜索,同时terms支持多个词语匹配检索
POST /{indexName}/_doc/_search
// term
{
"query": {
"term": {
{fieldName2}: {searchTxt2},
}
}
}
// terms
{
"query": {
"terms": {
{fieldName1}: [{searchTxt1}, {searchTxt2}...]
}
}
}
prefix关键字,根据前缀去查询
POST /{indexName}/_doc/_search
{
"query": {
"prefix": {
// {prefixTxt} 作为前缀
{fieldName}: {prefixTxt},
}
}
}
fuzzy关键字,在用户进行搜索时可能出现打错字的现象,搜索引擎会自动纠正,然后尝试匹配数据
POST /{indexName}/_doc/_search
{
"query": {
"fuzzy": {
{fieldName}: {errorWord}
}
}
}
ids关键字,根据主键 ID 搜索
POST /{indexName}/_doc/_search
{
"query": {
"ids": {
"type": "_doc",
"values": [{id1}, {id2}...]
}
}
}
1.2 布尔查询
- 布尔查询(多重组合查询)
must:查询必须匹配搜索条件,类似于 SQL 语句的andshould:查询匹配满足一个以上条件,类似于 SQL 语句的ormust_not:不匹配搜索条件,一个都不要满足- 有时候,搜索同一个文档字段属性,希望
搜索内容分词A比搜索内容分词B权重更高可以使用should模式并设置boost权重属性
POST /{indexName}/_doc/_search
// 使用 must 举例
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": {searchTxt1},
"fields": [{fieldName1}, {fieldName2}..]
}
},
{
"term": {
{fieldName3}: {searchTxt2}
}
},
{
"term": {
{fieldName4}: {searchTxt3}
}
},
...
}
]
}
}
}
// 同时使用 must,should,must_not 也是可以的
{
"query": {
"bool": {
"must": [
...
]
"should": [
...
]
"must_not": [
...
]
}
}
}
// 使用 should 时,可以添加权重,举例
{
"query": {
"bool": {
"should": [
{
"match": {
"desc": {
"query": "律师",
"boost": 18
}
}
},
{
"match": {
"desc": {
"query": "进修",
"boost": 2
}
}
}
]
}
}
}
1.3 过滤器
对搜索出来的结果进行数据过滤(即查询后,对结果数据的筛选),不会到 ES 库里去搜,不会计算文档的相关度分数,所以过滤的性能会比较高,过滤器可以和全文搜索结合在一起使用。
post_filter 元素和上述的 query 元素一样,都是顶层元素,但 post_filter 不会计算数据的匹配度相关性分数,不会据分数排序。
举例:
POST /{indexName}/_doc/_search
// term
{
"query": {
"term": {
{fieldName2}: {searchTxt2},
}
},
// money 字段属性需要大于 60,小于 100
"post_filter": {
"range": {
"money": {
"gt": 60,
"lt": 100
}
}
}
}
1.4 排序
sort 元素和上述的 query 元素一样,都是顶层元素。
POST /{indexName}/_doc/_search
// term
{
"query": {
"term": {
{fieldName2}: {searchTxt2},
}
},
"sort": [
{
{fieldName1}: "desc"
},
{
{fieldName2}: "asc"
}
...
]
}
对文本排序,由于文本会被分词,所以排序的时候就会不知道用哪个分词后的内容去进行排序,所以需要在一开始设置文档字段的时候额外添加一个附属属性 keyword,用于排序:
POST /{indexName}/_mapping
{
"properties": {
{fieldName}: {
"type": {typeName},
"analyzer": {analyzerName},
// 设置 keyword
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
1.5 关键字高亮显示
POST /{indexName}/_doc/_search
// term
{
"query": {
"term": {
{fieldName}: {searchTxt},
},
"term": {
{fieldName2}: {searchTxt2},
}
},
// 搜索词前后添加 span 标签
"highlight": {
"pre_tags": ["<span class="highlight">"],
"post_tags": ["</span>"],
"fields": {
{fieldName}:{},
{fieldName2}:{}
}
}
}
2 深度分页
深度分页其实就是指搜索的深浅度,比如第 10000 页,ES 在获取第 9999 条到 10009 条数据的时候,假如设置了多个主分片,那么它会从每个分片中拿出 10009 条数据集合在一起,再对这些汇总数据进行排序处理,最后获取对应的 10 数据,这样一来就会有性能的问题,ES 默认是不支持操作一万条数据以上的分页查询,而我们也应该避免深度分页操作(限制分页页数)
通过设置 index_max_result_window 来突破限制
PUT /{indexName}/_settings
{
"index_max_result_window": "20000"
}
2.1 scroll 滚动搜索
一次性查询一万加的数据,往往会造成性能影响,因为数据量太多,这时候就可以使用滚动搜索。
滚动搜索可以先查询出一些数据,然后再接着依次往下查询,查询的时候会返回一个滚动 ID,相当于一个 锚标记,接下来的每次查询都需要携带上一次返回的 锚标记,值得注意的是,如果有数据变更,搜索出来的数据也只是旧版本的数据。
第一次滚动查询:
// scroll=1m 相当于是一个session会话时间,搜索保持上下文1分钟
POST /{indexName}/_search?scroll=1m
{
"query": {
"match_all": {}
},
"sort": ["_doc"],
"size": 5 // 设置单页查询数量
}
后续查询:
POST /_search/scroll
{
"scroll": "1m", //相当于是一个session会话时间,搜索保持上下文1分钟
"scroll_id": {scroll_id}
}
3 批量操作
bulk 操作和以往的普通的请求格式有区别,它不能支持格式化 json,它的发送数据格式是:
{action:{metadata}}\n
{request body}\n
{action:{metadata}}\n
{request body}\n
...
{action:{metadata}}代表批量操作的类型,不同操作类型之间是可以混合在同一请求中使用的create:新增,如果文档不存在,就创建他,存在则会报错,但不影响其它操作index:创建或替换一个现有的文档update:部分更新文档delete:删除一个文档
\n即是回车符(不是填写\n进去请求体中,而是直接按回车键即可),每行结尾必须填写的规范(包括最后一行){request body}:增和改操作的内容,删除操作无需携带
metadata 中需要指定要操作的文档的 _index(索引表表名)、_type(固定值为 _doc)和 _id,其中 _index 和 _type 可以直接在 url 中指定。
create操作
POST /_bulk
// 或者 /{indexName}/_doc/_bulk 这样指定url的话,下方 metaData 就无需声明 _index 和 _type
{"create":{"_index":{indexName1},"_type":"_doc","_id":{id1}}}
{{fieldName1}: {value1}, {fieldName2}: {value2}}
{"create":{"_index":{indexName1},"_type":"_doc","_id":{id2}}}
{{fieldName1}: {value3}, {fieldName2}: {value4}}
{"create":{"_index":{indexName2},"_type":"_doc","_id":{id3}}}
{{fieldName3}: {value5}, {fieldName4}: {value6}}
index操作,创建或替换一个现有的文档
POST /{indexName}/_doc/_bulk
{"index":{"_id":{id1}}}
{{fieldName1}: {value1}, {fieldName2}: {value2}}
{"index":{"_id":{id2}}}
{{fieldName1}: {value3}, {fieldName2}: {value4}}
update操作,创建或替换一个现有的文档
POST /{indexName}/_doc/_bulk
{"update":{"_id":{id1}}}
{"doc":{{fieldName1}: {value1}, {fieldName2}: {value2}}}
{"index":{"_id":{id2}}}
{"doc":{{fieldName1}: {value3}, {fieldName2}: {value4}}}
delete操作,创建或替换一个现有的文档
POST /{indexName}/_doc/_bulk
{"delete":{"_id":{id1}}}
{"delete":{"_id":{id2}}}
本文深入探讨了Elasticsearch的DSL(Domain Specific Language)查询,包括基本搜索、布尔查询、过滤器、排序、关键字高亮等。DSL查询以其JSON格式的可读性和灵活性,适用于复杂的搜索场景。例如,`match_all`用于搜索所有文档,`match`和`multi_match`支持精确和多字段匹配,`bool`构造复杂的布尔表达式,`post_filter`进行高效的数据过滤,`sort`实现自定义排序,`highlight`高亮显示搜索词。此外,还介绍了如何处理深度分页问题,以及批量操作的`bulk`API使用方法。
&spm=1001.2101.3001.5002&articleId=124336805&d=1&t=3&u=daf144d50bf04ac0b0e3f8f7dfbfca8e)
2万+

被折叠的 条评论
为什么被折叠?



