diff --git a/elastic search/elastic search.md b/elastic search/elastic search.md index 61a4c3b..d2e1a9b 100644 --- a/elastic search/elastic search.md +++ b/elastic search/elastic search.md @@ -699,7 +699,204 @@ GET /cooking_blog/_search > - 如果`total.relation`为`eq`,则`total.value`代表实际hit count > - 如果`total.relation`为`gte`, 则`total.value`为hit count的下界,实际hit count大于或等于`total.value` - - +> ##### max score +> `max_score`代表所有matching documents中最高的relevance score + +> ##### _score +> _score为指定文档的relevance score,分数越高,匹配越好。 + +##### contains all terms +如上所示,如果在`query.match.description.query`中指定了多个由空格分隔的词,那么可以为`query.match.description.operator`指定`and`,那么其会查询description中包含所有分词的文档。 +``` +GET /cooking_blog/_search +{ + "query": { + "match": { + "description": { + "query": "fluffy pancakes", + "operator": "and" + } + } + } +} +``` + +##### 应匹配terms的最小个数 +通过`minimum_should_match`参数,可以指定在search result中最少应该匹配的terms个数。 + +如下实例中,查询文本中包含三个分词,`"fluffy", "pancakes", or "breakfast"`,但是查询结果中至少应该包含3个中的2个: +``` +GET /cooking_blog/_search +{ + "query": { + "match": { + "title": { + "query": "fluffy pancakes breakfast", + "minimum_should_match": 2 + } + } + } +} +``` +##### search across mutli fields +当用户输入查询文本时,其通常不知道是否查询文本出现在文档中的哪个字段。`multi_match`允许同时跨多个字段来进行查询。 + +mutli_match查询示例如下: +``` +GET /cooking_blog/_search +{ + "query": { + "multi_match": { + "query": "vegetarian curry", + "fields": ["title", "description", "tags"] + } + } +} +``` +在上述示例中,将会在`title, description, tags`三个字段中查询`vegetarian curry`,其中每个字段的重要性都相同。 + +但是,在某种场景下,在部分字段中的匹配比其他字段中的匹配更加重要(例如,相关论文检索时,关键词出现在摘要中要比出现在正文中更加重要)。 + +因此,可以在fields中针对多个字段进行重要性加权的调整: +``` +GET /cooking_blog/_search +{ + "query": { + "multi_match": { + "query": "vegetarian curry", + "fields": ["title^3", "description^2", "tags"] + } + } +} +``` +如上述示例所示,`^`语法应用于指定字段: +- `title^3`:title的重要性为非增强字段的3倍 +- `description^2`:description的重要性为非增强字段的2倍 +- `tags`:非增强字段 + +#### filter & exact matches +filter允许根据指定条件来缩小查询结果的范围。和full-text search不同的是,filter是二进制的,并且不会影响relevance score。 + +filter相较于query执行的更快,因为被排除的result不会计算score。 + +##### bool query +在如下示例中,`bool query`只会返回category为`Breakfast`中的文档: +``` +GET /cooking_blog/_search +{ + "query": { + "bool": { + "filter": [ + { "term": { "category.keyword": "Breakfast" } } + ] + } + } +} +``` +在针对`category`进行filter时,指定的是`category.keyword`,其类型为`keyword`,为`精确、区分大小写的匹配`。 + +> `category.keyword`字段其`multi field`类型为`keyword`,代表了字段`没有经过分析的版本`(代表字段没有指定analyzer),故而其进行的是精确、大小写敏感的匹配。 +> +> 如下两种场景将会使用`.keyword`: +> 1. 使用了针对`text`类型的字段使用了dynamic mappings,此时es会自动创建一个名为`.keyword`的`multi-field` +> 2. 当手动指定`text`类型字段的`.keyword`为`keyword`类型时 + +##### date range +当想要查询一定时间范围内的文档时,可以按如下方式来编写查询: +``` +GET /cooking_blog/_search +{ + "query": { + "range": { + "date": { + "gte": "2023-05-01", + "lte": "2023-05-31" + } + } + } +} +``` +##### exact match +可以通过`term`来搜索精确术语,term将会在字段中精确的搜索,`并不会对传入的文本进行分析`。 + +针对指定term的精确、大小写敏感搜索通常基于keyword进行搜索。 + +term搜索示例如下所示,搜索作者为`Maria Rodriguez`的文档: +``` +GET /cooking_blog/_search +{ + "query": { + "term": { + "author.keyword": "Maria Rodriguez" + } + } +} +``` + +> 应该避免在`text`类型的字段上使用`term`查询,因为`text`类型的field会被analyzer进行分析和转换 + +#### 组合搜索 +`bool query`允许将多个子查询组合为复杂的查询。 + +bool query示例如下: +``` +GET /cooking_blog/_search +{ + "query": { + "bool": { + "must": [ + { "term": { "tags": "vegetarian" } }, + { + "range": { + "rating": { + "gte": 4.5 + } + } + } + ], + "should": [ + { + "term": { + "category": "Main Course" + } + }, + { + "multi_match": { + "query": "curry spicy", + "fields": [ + "title^2", + "description" + ] + } + }, + { + "range": { + "date": { + "gte": "now-1M/d" + } + } + } + ], + "must_not": [ + { + "term": { + "category.keyword": "Dessert" + } + } + ] + } + } +} +``` +上述查询含义如下: +- tag中必须精确匹配vegetarian +- rating必须大于或等于4.5 +- 在title或者description中应该包含`curry`或`spicy` +- category应该精确匹配`Main Course` +- date字段应该大于或等于上个月 +- category不能为Dessert + +> ##### `must_not` +> `must_not`会淘汰不满足指定条件的文档