ElasticSearch 在string类型的字段上做排序出错的解决方案

问题

有个简单的需求:列出图书信息,并按照图书标题的字典顺序排列。

原来认为会很简单:

 

builder.addSort(SortBuilders.fieldSort("title").order(SortOrder.ASC));

 没想到确报这样的异常:

 

Can’t sort on string types with more than one value per doc, or more than one token per field
 

原因分析

 

根据异常信息的提示,有两个可能:

1) 文档里有两个string类型排序的字段

2) 排序的字段里有多个”token“

 

检查索引的文档,没有发现有多个”title“,那只能是第二个原因了。

一个字符串类型的字段,在mapping里通常是这样的:

 

"title":{
    "type":"string"
}

 并没有制定要不要做tokenize,不过看起来Elasticsearch默认是做了tokenize的。这也符合常理,毕竟是要在这个字段上做搜索的。但是做排序的需要也要满足。

还好已经有人提供解决方案了:对title 做 multi mapping (http://blog.wiercinski.net/2011/uncategorized/elasticsearch-sorting-on-string-types-with-more-than-one-value-per-doc-or-more-than-one-token-per-field/)

具体来说就是更改文档的mapping 为:

 

"title" : {
        "type" : "multi_field",
        "fields" : {
          "title" : {
            "type" : "string"
          },
          "untouched" : {
            "type" : "string",
            "index" : "not_analyzed",
            "include_in_all" : false
          }
        }
      }

 在做排序的时候需要调整为:

 

 

builder.addSort(SortBuilders.fieldSort("title.untouched").order(SortOrder.ASC));
 

后续问题 

到此问题应该就已经解决,可是重新调用功能,还是没有按照字典顺序排列。

怀疑是需要重新建立索引的问题。

github上有线程的插件可以重建索引:https://github.com/karussell/elasticsearch-reindex

可惜我使用下来并不顺利。

根据网上的php脚本做了些改动,实现了重建索引的功能,基本思路是这样的:

 

  1. 建立一个新的index
  2. 插入一条数据到新index中
  3. 修改elasticsearch默认生成的mapping
  4. 删除上步插入的记录(保留mapping)
  5. 通过scroll_search从旧index中读出数据到新index中。
  6. 删除旧index,然后重建
  7. 插入一条数据到旧index中
  8. 修改elasticsearch默认生成的mapping
  9. 删除上步插入的记录(保留mapping)
  10. 通过scroll_search从新index中读出数据到旧index中

这样,每个文档的title字段就有两个类型了,一个用于搜索,一个用于排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值