`
shuminghuang
  • 浏览: 52306 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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
1
分享到:
评论
2 楼 50341 2016-01-15  
朋友你好,我现在的问题是,已经有两个了,一个用于IK,一个用于pinyin,如果需要排序的话,是否需要在加一个multi_field?配置为not_analyzed?
1 楼 350530133 2013-09-27  
重建索引的没有必要来回倒腾吧?可以使用aliases来做索引映射。然后内部指定不同的名称如果index_version1,如果需要修改的话,只需要先建立好index_version2的mapping,然后慢慢的将数据从index_version1迁移到index_version2.迁移期间可以同时搜索两个索引。迁移完成后,将alias修改指向index_version2.

相关推荐

Global site tag (gtag.js) - Google Analytics