先看后赞,养成习惯。
点赞收藏,人生辉煌。
DSL是Domain Specific Language的缩写,指的是为特定问题领域设计的计算机语言。这种语言专注于某特定领域的问题解决,因而比通用编程语言更有效率。
在Elasticsearch(ES)中,DSL指的是Elasticsearch Query DSL,一种以JSON形式表示的查询语言。通过这种语言,用户可以构建复杂的查询、排序和过滤数据等操作。这些查询可以是全文搜索、分面/聚合搜索,也可以是结构化的搜索。
查询上下文
使用query关键字进行检索,倾向于相关度搜索,故需要计算评分。搜索是Elasticsearch最关键和重要的部分。
在查询上下文中,一个查询语句表示一个文档和查询语句的匹配程度。无论文档匹配与否,查询语句总能计算出一个相关性分数在_score
字段上。
相关度评分:_score
相关度评分用于对搜索结果排序,评分越高则认为其结果和搜索的预期值相关度越高,即越符合搜索预期值,默认情况下评分越高,则结果越靠前。在7.x之前相关度评分默认使用TF/IDF算法计算而来,7.x之后默认为BM25。
源数据:_source
source字段包含索引时原始的JSON文档内容,字段本身不建立索引(因此无法进行搜索),但是会被存储,所以当执行获取请求是可以返回source字段。
虽然很方便,但是source字段的确会对索引产生存储开销,因此可以禁用source字段,达到节省存储开销的目的。可以通过以下接口进行关闭。
PUT my_index { "mappings": { "_source": { "enabled": false } } }
但是需要注意的是这么做会带来一些弊端,_source禁用会导致如下功能无法使用:
- 不支持update、update_by_query和reindex API。
- 不支持高亮。
- 不支持reindex、更改mapping分析器和版本升级。
总结:在禁用source之前,应该仔细考虑是否需要进行此操作。如果只是希望降低存储的开销,可以压缩索引比禁用source更好。
数据源过滤器
例如,假设你的应用只需要获取部分字段(如"name"和"price"),而其他字段(如"desc"和"tags")不经常使用或者数据量较大,导致传输和处理这些额外的数据会增加网络开销和处理时间。在这种情况下,通过设置includes和excludes可以有效地减少每次请求返回的数据量,提高效率。例如:
PUT product { "mappings": { "_source": { "includes": ["name", "price"], "excludes": ["desc", "tags"] } } }
Including:结果中返回哪些field。
Excluding:结果中不要返回哪些field,不返回的field不代表不能通过该字段进行检索,因为元数据不存在不代表索引不存在,Excluding优先级比Including更高。
需要注意的是,尽管这些设置会影响搜索结果中_source字段的内容,但并不会改变实际存储在Elasticsearch中的数据。也就是说,"desc"和"tags"字段仍然会被索引和存储,只是在获取源数据时不会被返回。
在mapping中定义这种方式不推荐,因为mapping不可变。我们可以在查询过程中使用_source指定返回的字段,如下:
GET product/_search { "_source": { "includes": ["owner.*", "name"], "excludes": ["name", "desc", "price"] }, "query": { "match_all": {} } }
Elasticsearch的_source
字段在查询时支持使用通配符(wildcards)来包含或排除特定字段。使得能够更灵活地操纵返回的数据。
关于规则,可以参考以下几点:
- *:匹配任意字符序列,包括空序列。
- ?:匹配任意单个字符。
- [abc]: 匹配方括号内列出的任意单个字符。例如,[abc]将匹配"a", "b", 或 "c"。
请注意,通配符表达式可能会导致查询性能下降,特别是在大型索引中,因此应谨慎使用。
全文检索
全文检索是Elasticsearch的核心功能之一,它可以高效地在大量文本数据中寻找特定关键词。
在Elasticsearch中,全文检索主要依靠两个步骤:"分析"(Analysis)和"查询"(Search)。
- 分析: 当你向Elasticsearch索引一个文档时,会进行"分析"处理,将原始文本数据转换成称为"tokens"或"terms"的小片段。这个过程可能包括如下操作:
- 切分文本(Tokenization)
- 将所有字符转换为小写(Lowercasing)
- 删除常见但无重要含义的单词(Stopwords)
- 提取词根(Stemming)
- 查询: 当执行全文搜索时,查询字符串也会经过类似的分析过程,然后再与已经分析过的索引进行比对,找出匹配的结果并返回。
Elasticsearch提供了许多种全文搜索的查询类型,例如:
- Match Query: 最基本的全文搜索查询。
- Match Phrase Query: 用于查找包含特定短语的文档。
- Multi-Match Query: 类似Match Query,但可以在多个字段上进行搜索。
- Query String Query: 提供了丰富的搜索语法,可以执行复杂的、灵活的全文搜索。
match:匹配包含某个term的子句
GET product/_search { "query": { "match": { "name": "xiaomi nfc phone" } } }
上面的搜索语句,只要文档的"name"字段包含"xiaomi"、"nfc"或者"phone"中的任何一个词,就会被视为匹配。
match_all:匹配所有结果的子句
match_all
是 Elasticsearch 中的一个查询类型,它匹配所有文档,不需要任何参数。
GET product/_search { "query": { "match_all": {} } }
上面的语句等价于:
GET /product/_search
这个查询将会返回索引中的所有文档。这通常用于在没有特定搜索条件时获取所有的文档,或者与其他查询结合使用(如过滤器)。
需要注意,由于 match_all
查询可能返回大量的数据,所以一般在使用时都会与分页(pagination)功能结合起来,这样可以控制返回结果的数量,避免一次性加载过多数据导致的性能问题。例如,你可以使用 from
和 size
参数来限制返回结果:
GET /_search { "query": { "match_all": {} }, "from": 10, "size": 10 }
multi_match:多字段条件
multi_match
查询是 Elasticsearch 中用来在多个字段上执行全文查询的功能。它接受一个查询字符串和一组需要在其中执行查询的字段列表。例如:
GET /_search { "query": { "multi_match" : { "query": "xiaomi nfc phone", "fields": [ "name", "description" ] } } }`
这个查询会在 "name" 和 "description" 两个字段中查找包含 "xiaomi nfc phone" 的文档。
multi_match
还支持多种类型的匹配模式,如:best_fields
, most_fields
, cross_fields
, phrase
, phrase_prefix
等。这些类型的行为略有不同,可以按照实际需求进行选择。
例如,“best_fields” 类型会从指定的字段中挑选分数最高的匹配结果计算最终得分,而“most_fields” 类型则会在每个字段中都寻找匹配项并将其分数累加起来。
需要注意的是,当使用 multi_match
查询时,如果字段不同,其权重可能也会不同。你可以通过在字段名后面添加尖括号(^)和权重值来调整特定字段的权重。例如,"fields": [ "name^3", "description" ]
表示在"name"字段中的匹配结果权重是"description"字段的三倍。
match_phrase:短语查询
match_phrase
是 Elasticsearch 中的一种全文查询类型,它用于精确匹配包含指定短语的文档。match_phrase 查询需要字段值中的单词顺序与查询字符串中的单词顺序完全一致。
例如:
GET /_search { "query": { "match_phrase": { "message": "this is a test" } } }
这个查询将会找到"message"字段中包含完整短语"this is a test"的所有文档。
此外,match_phrase
查询还有一个 slop
参数,可以定义词组中的词语可能存在的位置偏移量。例如,如果将 slop
设置为 1,则查询 "this is a test" 也可匹配 "this is test a",因为 "a" 和 "test" 只需移动一个位置即可匹配。