• 【elasticsearch】记录ES查询数据结果为空的问题(单个字搜索可以,词语搜索为空)


    本文目录

    一、基本环境

    二、问题现象

    三、案例介绍

    四、问题原因

    五、解决方案

    第一步:删除索引

    第二步:重建索引

    第三步:触发程序灌数据

    六、总结


    一、基本环境

    • elasticsearch 版本:7.11.1
    • 客户端环境:kibana v7.11.1、Java8 应用程序模块。

    其中 kibana 主要用于数据查询诊断和查阅日志,Java8 为主要的客户端,数据插入和查询都是由Java 实现的。

    二、问题现象

    共有三个部署环境,一个是开发环境、一个是测试环境、一个是正式环境。

    前提:APP的首页搜索功能(搜索设备列表和搜索智能列表)在开发环境和正式环境一切正常。

    测试人员在测试APP的首页搜索功能(搜索设备列表和搜索智能列表),发现搜索智能列表功能正常,而搜索设备时,无数据。

    使用 kibana 里的开发工具查询时单个汉字可以搜索出设备列表,而使用词语去搜索设备时一直搜索不到任何数据。

    查询数据命令:命令 索引/_search

    下图中的命令是查询该索引下的所有数据

    示例(根据某一字段查询)如下:

    1. GET device-name-index/_search
    2. {
    3. "query": {
    4. "bool": {
    5. "must": [
    6. {"term": {
    7. "deviceName": {
    8. "value": "开关"
    9. }
    10. }}
    11. ]
    12. }
    13. }
    14. }

    搜索“开”字可以把设备名称中带有“开”字的设备搜索出来,但是搜索“开关”词语时,设备名称中带有“开关”词语的设备结果为空(ES中实际上有数据)。

    三、案例介绍

    使用 elasticsearch 存储设备列表的主要信息,document 内的 field,基本上是 integer keywordes 自动创建的索引 device-name-index 如下:

    查询 mapping 信息,命令如下:

    GET device-name-index/_mapping

    结果返回如下:

    1. {
    2. "device-name-index" : {
    3. "mappings" : {
    4. "properties" : {
    5. "deviceId" : {
    6. "type" : "integer"
    7. },
    8. "deviceModel" : {
    9. "type" : "text"
    10. },
    11. "deviceName" : {
    12. "type" : "text"
    13. },
    14. "deviceType" : {
    15. "type" : "text"
    16. },
    17. "floorName" : {
    18. "type" : "text"
    19. },
    20. "id" : {
    21. "type" : "integer"
    22. },
    23. "roomName" : {
    24. "type" : "text"
    25. },
    26. "sn" : {
    27. "type" : "text"
    28. }
    29. }
    30. }
    31. }
    32. }

    而部署在开发环境里的 es 索引里的字段类型如下:

    1. {
    2. "device-name-index" : {
    3. "mappings" : {
    4. "properties" : {
    5. "deviceId" : {
    6. "type" : "integer"
    7. },
    8. "deviceModel" : {
    9. "type" : "keyword"
    10. },
    11. "deviceName" : {
    12. "type" : "text",
    13. "fields" : {
    14. "ikmaxword" : {
    15. "type" : "text",
    16. "analyzer" : "ik_max_word"
    17. },
    18. "pinyin" : {
    19. "type" : "text",
    20. "analyzer" : "pinyin"
    21. }
    22. },
    23. "analyzer" : "standard"
    24. },
    25. "deviceType" : {
    26. "type" : "keyword"
    27. },
    28. "floorName" : {
    29. "type" : "keyword"
    30. },
    31. "roomName" : {
    32. "type" : "keyword"
    33. },
    34. "sn" : {
    35. "type" : "keyword"
    36. }
    37. }
    38. }
    39. }
    40. }

    以上字段,只需要关注 deviceName 即可。因为搜索是根据此字段检索数据的。

    可以很清楚的看到 deviceName 字段使用了 ik分词器(ik_max_word)。

    四、问题原因

    按照 mapping 返回结果来看,部署在测试环境的字段 deviceName 没有添加 ik 分词器,而 es 采取的策略是,如果没有添加自定义的分词器,那么便会使用 es 默认的标准分词器分词,这就是导致单个字搜索时可以检索出数据,而使用词语检索数据时无数据的原因。

    五、解决方案

    第一步:删除索引

    命令如下:

    DELETE device-name-index

    第二步:重建索引

    命令如下:

    1. PUT device-name-index
    2. {
    3. "mappings": {
    4. "properties": {
    5. "deviceId": {
    6. "type": "integer"
    7. },
    8. "deviceModel": {
    9. "type": "keyword"
    10. },
    11. "deviceName": {
    12. "type": "text",
    13. "fields": {
    14. "ikmaxword": {
    15. "type": "text",
    16. "analyzer": "ik_max_word"
    17. },
    18. "pinyin": {
    19. "type": "text",
    20. "analyzer": "pinyin"
    21. }
    22. },
    23. "analyzer": "standard"
    24. },
    25. "deviceType": {
    26. "type": "keyword"
    27. },
    28. "floorName": {
    29. "type": "keyword"
    30. },
    31. "roomName": {
    32. "type": "keyword"
    33. },
    34. "sn": {
    35. "type": "keyword"
    36. }
    37. }
    38. }
    39. }

    第三步:触发程序灌数据

    在我的项目中只需要修改设备名称即可触发数据内容变更(全量删除并全量更新),再次在APP首页搜索设备名称,单个字和词语都可以检索出数据,问题搞定。

    使用ik分词器后,查看分词结果情况,命令格式:

    GET 索引/_doc/索引下某字段_id/_termvectors?fields=字段名称.ikmaxword

    使用es默认的分词器查看分词结果情况,命令:

    GET 索引/_doc/索引下某字段_id/_termvectors?fields=字段名称

    示例如下:

    GET device-name-index/_doc/cO-TNIMBWdpBXCOgNBnM/_termvectors?fields=deviceName.ikmaxword

    六、总结

    问题虽小,但一定要追溯源头,比如此次测试环境的不规范操作。后期如果有删除索引的操作,应该先手动建立索引后,再灌数据,而不是直接让其自动 mapping 建立索引,自动 mapping 建立的字段类型,可能不是我们期望的。

    完结!

  • 相关阅读:
    【计算机网络】第一章 概述
    【趣学Python算法100例】兔子产子
    论文解析——AMD EPYC和Ryzen处理器系列的开创性的chiplet技术和设计
    【智慧导诊系统源码】智慧导诊系统的技术支撑与实际运作
    纯前端实现的验证码
    Extended-csv-dataset-config_Jmeter插件推荐
    vue window.print()打印多页页面指定内容 纯前端
    C++的缺省参数、函数重载和引用
    通过源码来理解Cglib与JDK动态代理
    Rancher部署K8S集群
  • 原文地址:https://blog.csdn.net/weixin_44299027/article/details/126833885