Elasticsearch:按字母顺序排序西班牙双姓

4

我正在进行Elasticsearch查询,我想要按照姓氏字母顺序排序结果。我的问题是:这些姓氏都是西班牙式的双重姓名,ES并不能按照我期望的方式进行排序。 我希望排序的顺序如下:

Batres Rivera
Batrín Chojoj
Fion Morales
Lopez Giron
Martinez Castellanos
Milán Casanova

这是我的查询:

{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "Last Name": {
        "order": "asc"
      }
    }
  ]
}

我获得的顺序是:
Batres Rivera
Batrín Chojoj
Milán Casanova
Martinez Castellanos
Fion Morales
Lopez Giron

因此,它不是按照第一个字符串排序,而是根据两者之一进行排序(Batres、Batrín、Casanova、Castellanos、Fion、Giron)。
如果我尝试进行其他操作

{
    "order": "asc",
    "mode": "max"
}

然后我得到:

Batrín Chojoj
Lopez Giron
Martinez Castellanos
Milán Casanova
Fion Morales
Batres Rivera

所有字段默认都是索引的,我已经确认过了

curl -XGET localhost/my_index/_mapping 

并且我得到了回复

my_index: {
    my_type: {
        properties: {
            FirstName: {
                type: string
            }LastName: {
                type: string
            }MiddleName: {
                type: string
            }
            ...
        }
    }
}

有没有人知道如何通过姓氏的开头字符串按字母顺序对结果进行排序?

谢谢!


你对答案有什么遗漏吗?如果没有,请接受它。 - DrTech
抱歉,我以为我已经完成了,现在完成了。 不,没有遗漏,谢谢! - morninlark
2个回答

14
问题在于你的LastName字段被分析了,所以字符串Batres Rivera被索引为一个包含两个项的多值字段:batresrivera。但这不像一个有序数组,更像是一个“价值袋”。因此,当你尝试按照该字段排序时,它会选择其中一个项(minmax)并对其进行排序。
为了排序目的,你需要将LastName存储为单个项(Batres Rivera),通过将该字段映射为:
{ "type": "string", "index": "not_analyzed"}

显然,您不能将该字段用于搜索目的:您将无法搜索 rivera 并在该字段上进行匹配。

支持搜索和排序的方法是使用多字段:即以两种方式索引相同的值,一种用于搜索,一种用于排序。

在0.90.*中,多字段的语法如下:

curl -XPUT "http://localhost:9200/my_index" -d'
{
   "mappings": {
      "my_type": {
         "properties": {
            "LastName": {
               "type": "multi_field",
               "fields": {
                  "LastName": {
                     "type": "string"
                  },
                  "raw": {
                     "type": "string",
                     "index": "not_analyzed"
                  }
               }
            }
         }
      }
   }
}'

在1.0.*版本中,multi_field类型已被移除,现在任何核心字段类型都支持如下的子字段:

curl -XPUT "http://localhost:9200/my_index" -d'
{
   "mappings": {
      "my_type": {
         "properties": {
            "LastName": {
               "type": "string",
               "fields": {
                  "raw": {
                     "type": "string",
                     "index": "not_analyzed"
                  }
               }
            }
         }
      }
   }
}'

所以您可以使用LastName字段进行搜索,并使用LastName.raw字段进行排序:

curl -XGET "http://localhost:9200/my_index/my_type/_search" -d'
{
   "query": {
      "match": {
         "LastName": "rivera"
      }
   },
   "sort": "LastName.raw"
}'

语言特定的排序

您还应该考虑使用ICU分析插件,以使用西班牙排序(或整理)进行排序。这有点复杂,但值得使用:

curl -XPUT "http://localhost:9200/my_index" -d'
{
   "settings": {
      "analysis": {
         "analyzer": {
            "folding": {
               "type": "custom",
               "tokenizer": "icu_tokenizer",
               "filter": [
                  "icu_folding"
               ]
            },
            "es_sorting": {
               "type": "custom",
               "tokenizer": "keyword",
               "filter": [
                  "lowercase",
                  "spanish"
               ]
            }
         },
         "filter": {
            "spanish": {
               "type": "icu_collation",
               "language": "es"
            }
         }
      }
   },
   "mappings": {
      "my_type": {
         "properties": {
            "LastName": {
               "type": "string",
               "analyzer": "folding", 
               "fields": {
                  "raw": {
                     "type": "string",
                     "analyzer": "es_sorting"
                  }
               }
            }
         }
      }
   }
}'

我们创建了一个名为folding的分析器,用于处理LastName字段。它将把像Muñoz Rivera这样的字符串分析成两个术语munoz(不带~)和rivera。因此用户可以搜索munozmuñoz,任何一个都可以匹配。

然后我们创建了es_sorting分析器,以西班牙语的适当排序方式索引muñoz rivera(小写)。

搜索方式也是相同的:

curl -XGET "http://localhost:9200/my_index/my_type/_search" -d'
{
   "query": {
      "match": {
         "LastName": "rivera"
      }
   },
   "sort": "LastName.raw"
}'

0

我之前没有创建映射。 - morninlark
嗯,我真的看不出这怎么能帮助我。我还没有使用分析器。我必须使用分析器才能进行排序吗?另外,我无法访问任何http://www.elasticsearch.com/docs/...-links链接,因为我不是付费客户。 - morninlark
请问您索引了哪些字段?您是如何对文档进行索引的? - Vamsi Krishna
好的。是否可能通过以下命令输出更新问题: curl -XGET '127.0.0.1:9200/my_index/_mapping?pretty' - Vamsi Krishna
你似乎有些怀疑。没问题。请在上述命令中填写数据库中文档的id并更新问题,以获取curl -XGET '127.0.0.1:9200/my_index/my_type/<id>?pretty'的输出结果。 - Vamsi Krishna
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接