经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Elasticsearch » 查看文章
记一次ES查询数据突然变为空的问题
来源:cnblogs  作者:清茶豆奶  时间:2019/11/5 10:12:07  对本文有异议

基本环境

  • elasticsearch版本:6.3.1
  • 客户端环境:kibana 6.3.4、Java8应用程序模块。
    其中kibana主要用于数据查询诊断和查阅日志,Java8为主要的客户端,数据插入和查询都是由Java实现的。

案例介绍

使用elasticsearch存储订单的主要信息,document内的field,基本上是long或keyword,创建索引的order.json文件如下:

  1. {
  2. "doc": {
  3. "properties": {
  4. "id": {
  5. "type": "keyword",
  6. "index": true
  7. },
  8. "status": {
  9. "type": "byte",
  10. "index": true
  11. },
  12. "createTime": {
  13. "type": "long",
  14. "index": true
  15. },
  16. "uid": {
  17. "type": "long",
  18. "index": true
  19. },
  20. "payment": {
  21. "type": "keyword",
  22. "index": true
  23. },
  24. "commentStatus": {
  25. "type": "byte",
  26. "index": true
  27. },
  28. "refundStatus": {
  29. "type": "byte",
  30. "index": true
  31. }
  32. }
  33. }
  34. }

某天发现有个查询功能(单独使用payment字段查询)没有数据出来,最近未修改此部分代码。对比研发环境,研发环境是正常的,同样的代码在测试环境下无数据返回。

问题定位

  • 程序中使用该字段用的是termQuery,如下:
  1. QueryBuilders.termQuery("payment", req.getFilter().getOrder().getPayment())

在kibana上用命令诊断查询数据,同样没有结果返回,查询命令如下:

  1. GET /order/doc/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. {"term": {
  7. "payment": "Alipay"
  8. }}
  9. ]
  10. }
  11. }
  12. }
  • 查询mapping信息,看是否为keyword:

GET /order/_mapping/doc

响应返回(只展示payment字段):

  1. {
  2. "order": {
  3. "mappings": {
  4. "doc": {
  5. "properties": {
  6. "payment": {
  7. "type": "text",
  8. "fields": {
  9. "keyword": {
  10. "type": "keyword",
  11. "ignore_above": 256
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }

问题原因

按照mapping返回结果来看,字段payment原定义的类型是keyword,现在变成text了,这个是payment字段使用termQuery查询导致没有数据的原因。

text与keyword的区别

keyword对保存的内容不分词,也不改变大小写,原样存储,默认可索引。
text对内容进行分词,并且全部小写存储,同时会增加一个text.keyword字段,为keyword类型,超过256字符后不索引。

由于payment字段变成text了,原有的程序使用term查询,用的"Alipay",而text存储的是"alipay",所以查不到数据了。

尝试排错方法

  • payment的值改成小写
  1. GET /order/doc/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. {"term": {
  7. "payment": "alipay"
  8. }}
  9. ]
  10. }
  11. }
  12. }
  • 或将term查询改成match查询
  1. GET /order/doc/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. {
  7. "match": {
  8. "payment": "alipay"
  9. }
  10. }
  11. ]
  12. }
  13. }
  14. }

查询有数据输出,并且符合预期,尝试方法有效。

问题追溯

明明order.json的对payment字段定义的类型是keyword,怎么变成text了?

由于出现此问题的环境是测试环境,有重删索引数据,然后再全部导入的操作(有点不规范,但仅限于测试环境,生产环境不会这么做),重新导入索引document数据的功能,es创建索引自动mapping时,payment字段的string内容,会变成text。

解决办法:

1.删除索引

DELETE /order

2.按照order.json重建索引

  1. PUT /order
  2. {
  3. "mappings": {
  4. "doc": {
  5. "properties": {
  6. "id": {
  7. "type": "keyword",
  8. "index": true
  9. },
  10. "status": {
  11. "type": "byte",
  12. "index": true
  13. },
  14. "createTime": {
  15. "type": "long",
  16. "index": true
  17. },
  18. "uid": {
  19. "type": "long",
  20. "index": true
  21. },
  22. "payment": {
  23. "type": "keyword",
  24. "index": true
  25. },
  26. "commentStatus": {
  27. "type": "byte",
  28. "index": true
  29. },
  30. "refundStatus": {
  31. "type": "byte",
  32. "index": true
  33. }
  34. }
  35. }
  36. }
  37. }

3.触发程序灌数据(也可以用bulk)

小结

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

专注Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区
Java架构社区

原文链接:http://www.cnblogs.com/huangying2124/p/11796112.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号