ElasticSearch-查询 忽略大小写 完全匹配查询

本文介绍如何在Elasticsearch中创建一个索引,该索引在搜索时会忽略大小写差异,确保了特殊字符和大小写不会影响到搜索结果的一致性和准确性。

创建索引 忽略大小写

PUT /ecommerce
{
  "settings": {
    "analysis": {
      "normalizer": {
        "my_normalizer": {
          "type": "custom",
          "char_filter": [],
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  },
  "mappings": {
    "product": {
      "properties": {
        "producer": {
          "type": "keyword",
          "normalizer": "my_normalizer"
        }
      }
    }
  }
}

插入几条数据

PUT /ecommerce/product/1
{
    "producer" :    "Special"
}

PUT /ecommerce/product/4
{

    "producer" :      "special yagao producer"
}
PUT /ecommerce/product/5
{

    "producer" :      "sPecIal yagao producer"
}

完全匹配查询

GET /ecommerce/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "producer": {
              "value": "special"
            }
          }
        }
      ]
    }
  }
}

https://www.elastic.co/guide/en/elasticsearch/reference/6.0/normalizer.html

<think> 我们被要求使用Elasticsearch的_search API进行精确查询。与直接通过_id查询(GET /index/_doc/id)不同,_search API用于执行更复杂的查询,包括精确查询。 根据引用[1]和引用[2],_search API可以通过请求体(request body)来构造查询。对于精确查询,我们通常使用term查询(用于keyword类型字段)或terms查询(用于多个值)或者使用match_phrase(如果是文本且需要完全匹配)?但是注意:精确查询通常针对不分词的字段(keyword)使用term查询。 注意:引用[1]中提到,match查询会使用分词器,因此不适合精确查询。而引用[3]中给出了一个使用term查询的例子(在bool查询的must中)。 因此,使用_search API进行精确查询的方法如下: 1. 确定要查询的字段是keyword类型(如果是文本字段,默认可能被分词,精确查询需要使用.keyword子字段)。 2. 使用term查询(单个值)或terms查询(多个值)来匹配精确值。 示例:假设我们要在索引`my_index`中精确查询`status`字段值为200的文档。 请求: ``` GET /my_index/_search { "query": { "term": { "status": { "value": 200 } } } } ``` 或者更简洁的写法(如果不需要额外参数): ``` GET /my_index/_search { "query": { "term": { "status": 200 } } } ``` 但是,如果字段是文本类型(text)并且我们想要精确匹配整个字符串,那么应该使用`.keyword`(假设该字段有keyword子字段,这是Elasticsearch的常见映射设置)。例如,精确查询`name`为"John Smith"的文档: ``` GET /my_index/_search { "query": { "term": { "name.keyword": "John Smith" } } } ``` 另外,引用[1]中还提到,可以使用`match_phrase`进行不拆分的模糊查询?实际上,`match_phrase`是用于短语匹配,它要求所有的分词项都存在且顺序一致,并且位置连续。对于完全精确匹配(包括空格和大小写)的字符串,使用`term`加`.keyword`更合适。 因此,总结精确查询的两种常见情况: - 数值、日期、布尔等非文本类型:直接使用`term`查询- 字符串类型且需要精确匹配(整个字符串完全匹配):使用`term`查询并指定`.keyword`子字段。 另外,多值精确查询可以使用`terms`查询(相当于SQL中的IN): ``` GET /my_index/_search { "query": { "terms": { "status": [200, 201, 404] } } } ``` 注意:引用[2]指出,搜索API可以使用GET或POST,并且可以在路径中指定索引,也可以使用`_search`(所有索引)。我们通常指定索引。 下面给出一个完整的示例,包括过滤字段和分页(参考引用[1]中的`_source`和`from/size`): 示例:在`users`索引中,精确查询`city`字段为"New York"(注意:city字段是keyword类型)的文档,并只返回`name`和`age`字段,从第0条开始,返回10条。 请求: ``` GET /users/_search { "query": { "term": { "city.keyword": "New York" } }, "_source": ["name", "age"], "from": 0, "size": 10 } ``` 注意:如果字段映射为text类型,并且没有keyword子字段,那么精确查询可能会失效。因此,确保映射正确。 另外,如果查询字符串类型字段时,使用term查询且不加.keyword,那么查询的是分词后的词项。例如,如果"New York"被分词为["new", "york"],那么查询"New York"(作为一个整体)将不会匹配,而查询分词后的单个词(如"new")会匹配。 最后,如果我们需要同时满足多个精确条件,可以使用bool查询组合多个term查询(如引用[3]所示)。例如,查询city为"New York"且status为1的文档: ``` GET /users/_search { "query": { "bool": { "must": [ { "term": { "city.keyword": "New York" } }, { "term": { "status": 1 } } ] } } } ``` 以上即为使用_search API进行精确查询的方法。 现在,我们生成相关问题: 1. 在Elasticsearch中,如何为字符串字段同时设置text和keyword类型? 2. 使用term查询时,为什么有时查询不到预期的文档? 3. Elasticsearch中如何实现多字段的精确查询(多个条件)? </think> ### Elasticsearch REST API 使用 `_search` 进行精确查询的方法 在 Elasticsearch 中,通过 `_search` API 实现精确查询需要使用特定的查询语法(如 `term` 或 `match_phrase`),并结合字段类型(如 `keyword`)确保精确匹配。以下是详细方法和示例: --- #### 1. **核心方法:使用 `term` 查询** 当字段是 **`keyword` 类型**(未分词)时,使用 `term` 查询可实现精确匹配: ```bash GET /your_index/_search { "query": { "term": { "field_name.keyword": { # 使用.keyword子字段 "value": "exact_value" # 严格匹配的值 } } } } ``` - **适用场景**:数值、ID、状态码、未分词的字符串(如邮箱、邮编)。 - **关键点**: - 必须使用 `.keyword` 子字段(确保不分词)[^1]。 - 查询大小写敏感(如 `"Active"` ≠ `"active"`)。 --- #### 2. **文本字段的精确查询:`match_phrase`** 当字段是 **`text` 类型**(分词存储)时,使用 `match_phrase` 匹配完整词组: ```bash GET /your_index/_search { "query": { "match_phrase": { "description": "完整未拆分的词组" # 如 "Elasticsearch 教程" } } } ``` - **特点**: - 要求单词顺序和间隔完全一致。 -忽略分词器(如停用词),但保留空格和标点[^1]。 --- #### 3. **多条件精确查询:`bool` + `must`** 组合多个精确条件(类似 SQL 的 AND): ```bash GET /orders/_search { "query": { "bool": { "must": [ # 所有条件必须满足 { "term": { "status.keyword": "paid" } }, # 精确匹配状态 { "term": { "amount": 100 } } # 精确匹配数值 ] } }, "_source": ["order_id", "product"], # 返回指定字段[^1] "size": 10 # 分页控制[^1] } ``` --- #### 4. **精确查询 vs 模糊查询** | 查询类型 | 语法 | 是否分词 | 适用字段 | 示例值 | |----------------|---------------|----------|---------------|-------------| | 精确查询 (`term`) | `term` | 否 | `keyword` | `"error_404"` | | 短语查询 (`match_phrase`) | `match_phrase` | 是(但整体匹配) | `text` | `"系统错误"` | | 模糊查询 (`match`) | `match` | 是 | `text` | `"数据库"`(匹配"数据"或"库") | --- #### 5. **完整示例** **目标**:在 `products` 索引中精确查询分类为 `"electronics"` 且价格等于 `599` 的商品。 ```bash GET /products/_search { "query": { "bool": { "must": [ { "term": { "category.keyword": "electronics" } }, # 精确匹配分类 { "term": { "price": 599 } } # 精确匹配价格 ] } }, "_source": ["name", "price"], # 只返回名称和价格 "sort": [{"price": "asc"}], # 价格升序排序[^1] "size": 5 # 返回5条结果 } ``` **响应示例**: ```json { "hits": { "hits": [ { "_source": { "name": "无线耳机", "price": 599 } }, { "_source": { "name": "智能手表", "price": 599 } } ] } } ``` --- #### 6. **注意事项** 1. **字段类型决定查询方式**: - 数值/枚举字段 → 直接用 `term`。 - 字符串字段 → 用 `.keyword` 子字段避免分词[^1]。 2. **性能优化**: - 对精确查询字段启用 `eager_global_ordinals` 提升速度。 - 使用 `_source` 过滤减少网络传输[^1]。 3. **错误排查**: -查询无结果,检查字段映射类型(`GET /index/_mapping`)。 - 确保查询值无多余空格或大小写不一致。 --- #### 相关问题
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cocktail_py

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值