1 在项目中,产品已经上线一段时间,出现新的需求,需要解决查询的时候,忽略大小写的问题。本人用于测试的索引结构如下



PUT test_v1.000
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 5
  },
  "mappings": {
    "product": {
      "properties": {
        "name":{
          "type": "keyword"
        },
        "sex":{
          "type": "keyword"
        },
        "content":{
          "type": "text",
          "fields": {
            "keyword":{
              "ignore_above": 32766,
              "type": "keyword"
            }
          }
        }
      }
    }
  },
  "aliases": {
    "test": {}
  }
}


2 在test索引里面新增几条数据,用于查询使用


PUT test/product/_bulk
{"index":{"_id":5}}
{ "name": "New York5","sex":"男","content":"ES5.X版本以后,keyword支持的最大长度为32766个UTF-8字节数(至于多少个字符数需要根据业务场景定,建议参考最新版本的官方文档说明),text对字符长度没有限制。New York5"}
{"index":{"_id":6}}
{ "name": "new York6","sex":"男","content":"ES5.X版本以后,keyword支持的最大长度为32766个UTF-8字节数(至于多少个字符数需要根据业务场景定,建议参考最新版本的官方文档说明),text对字符长度没有限制。new York6"}
{"index":{"_id":7}}
{ "name": "New york7","sex":"男","content":"ES5.X版本以后,keyword支持的最大长度为32766个UTF-8字节数(至于多少个字符数需要根据业务场景定,建议参考最新版本的官方文档说明),text对字符长度没有限制。New york7"}
{"index":{"_id":8}}
{ "name": "NEW YORK8","sex":"男","content":"ES5.X版本以后,keyword支持的最大长度为32766个UTF-8字节数(至于多少个字符数需要根据业务场景定,建议参考最新版本的官方文档说明),text对字符长度没有限制。NEW YORK8"}


3 想查询name以及content.keyword里面的数据,但是需要忽略大小写的问题,测试如下,由于此时elasticsearch的mapping未做任何处理,是不会自动忽略大小写的,所以此时下面的查询语句,应该只能查询两条数据,id为2和6的数据。截图如下


POST test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "fields": ["content.keyword","name"],
            "query": "*new*"
          }
        }
      ]
    }
  }
}




es multi_match 不区分大小写 es查询忽略大小写_字段



4 对于elasticsearch查询忽略大小写的问题,官方给出了一个解决方案,使用normalizer来解决,normalizer是keyword的一个属性,可以对keyword生成的单一term,query_string做进一步的处理,比如lowercase,小写转换,使用方式和自定义分词器有相似之处,需要自定义,具体步骤如下。



5 此时由于elasticsearch的索引已经建好,由于es的规则,只能新增字段,不能删除或者修改已经存在的字段,可以动态更新原有索引的setting,动态更新setting,需要先关闭索引,执行玩更新操作以后,再开启索引,步骤如下


POST test/_close

PUT test/_settings
{
  "index": {
    "analysis": {
      "normalizer": {
        "lowercase_normalizer": {
          "type": "custom",
          "char_filter": [],
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  }
}

POST test/_open


6 查看原有test的索引setting,如下图,发现设置已经生效,这个时候,动态添加新的字段(keyword类型),既可使用lowercase_normalizer,实现忽略大小写的操作。




动态添加一个字段 author,如下,然后查看mapping,发现已经生效,并且author比其他keyword字段多一个属性normalizer


PUT test/product/_mapping
{
  "properties": {
    "author": {
      "type": "keyword",
      "normalizer": "lowercase_normalizer"
    }
  }
}



es multi_match 不区分大小写 es查询忽略大小写_数据_02



7 新增一条数据,并且测试,看查询author字段的时候,忽略大小写的操作是否已经实现,具体插入数据不再展示,自行插入数据,查询语句以及结果如下。发现查询da也能将包含DA的数据查询出来,说明已经实现了新增字段忽略大小写的操作。但是对老数据老字段,这种方式并不能解决问题,所以只能新增索引,将老数据同步过去,让我们继续往下操作



es multi_match 不区分大小写 es查询忽略大小写_数据_03



8 新建一个新索引,设置normalizer属性,命令如下


PUT xsj_test_v1.000
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 5,
    "analysis": {
      "normalizer": {
        "lowercase_normalizer": {
          "type": "custom",
          "char_filter": [],
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "product": {
      "properties": {
        "name":{
          "type": "keyword",
           "normalizer": "lowercase_normalizer"
        },
        "sex":{
          "type": "keyword",
           "normalizer": "lowercase_normalizer"
        },
         "author":{
          "type": "keyword",
           "normalizer": "lowercase_normalizer"
        },
        "content":{
          "type": "text",
          "fields": {
            "keyword":{
              "ignore_above": 32766,
              "type": "keyword",
               "normalizer": "lowercase_normalizer"
            }
          }
        }
      }
    }
  },
  "aliases": {
    "xsj_test": {}
  }
}


POST /_reindex
{
  "source": {
    "index": "test"
  },
  "dest": {
    "index": "xsj_test"
  }
}


10 测试name以及content.keyword字段,看是否忽略大小写操作已经生效。查询命令以及结果如下,发现query_string查询的时候,忽略大小写的操作已经生效,并且老数据也可以忽略大小写查询。


POST xsj_test/product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "fields": ["name","author","content.keyword"],
            "query": "*new*"
          }
        }
      ]
    }
  }
}

es multi_match 不区分大小写 es查询忽略大小写_数据_04