包含特殊字符数字和alpahbets的弹性搜索排序字段

时间:2015-09-29 20:29:02

标签: java sorting elasticsearch

我创建了一个不区分大小写的分析器

PUT /dhruv3
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "analyzer_keyword": {
            "tokenizer": "keyword",
            "filter": [ "lowercase", "asciifolding" ]
          }
        }
      }
    }
  },
  "mappings": {
    "test": {
      "properties": {
        "about": {
          "type": "string",
          "analyzer": "analyzer_keyword"
        },
        "firsName": {
          "type": "string"
        }
      }
    }
  }
}

并在映射中使用它。关于字段应该包含aplha numerc和特殊字符。然后我用about字段插入一些值为

  1234年,`朋友,朋友,〜朋友

。 除了搜索,我还需要对结果进行排序。搜索工作正常 但是当我尝试将它们排序为

GET dhruv/test/_search
{
  "sort": [
    {
      "about": {
        "order": "asc"
      }
    }
  ]
}

我得到关于字段的结果

  

1234,`PAL,PAL,PAL〜

。但我希望它们可以作为第一个特殊字符,然后是数字,然后是字母。

我做了一些家庭工作,并且因为他们的ASCII值而开始知道它。所以我搜索了互联网并尝试了asciifolding。但没有成功。我知道有一些解决方案,但我无法弄明白。请指导我

2 个答案:

答案 0 :(得分:3)

你说得对,你看到的排序行为是由于特殊字符的ASCII值大于数字的ASCII值。确切地说,查看ASCII table,我们有以下值:

  • 1的ASCII值为49
  • `具有ASCII值96
  • p的ASCII值为112
  • ~的ASCII值为126

asciifolding token filter只是将ASCII表中的 NOT 字符和数字(即前127个字符)转换为ASCII等效字符(如果存在)(例如éèëê转换为e)。由于上面的所有字符都在ASCII表中,因此这不是您要查找的内容。

如果你想在搜索中首先出现特殊字符,有几种方法。

实现它的一种方法是简单地否定它们的ASCII值,以便它们始终位于ASCII 0字符之前,然后使用脚本排序:

{
  "sort": [
    {
      "_script": {
        "script": "return doc['about'].value.chars[0].isLetterOrDigit() ? 1 : -1",
        "type": "number",
        "order": "asc"
      }
    }
  ]
}

答案 1 :(得分:1)

asciifolding与您尝试实现的目标无关。 ASCIIFoldingFilter.java有大量信息,它只是将\uFF5E之类的unicode字符解码为其ASCII等效字符,以防可以提供其中一个。

添加到@Val's的答案,如果你想要按特殊字符顺序排序的值然后是数字然后是字母表,你可能要考虑使用 -

GET /ascii/test/_search
{
  "sort": {
    "_script": {
      "script": "r = doc['about'].value.chars[0]; return !r.isLetter() ? r.isDigit() ? 1 : -1 : 2",
      "type": "number",
      "order": "asc"
    }
  }
}

另外,请注意这种排序可能并不完美,因为我们只处理脚本中的第一个字符。您可能希望编写一个可以处理整个值的健壮脚本。

这个gist是使用嵌入式脚本可以实现的一个很好的例子。