【问题标题】:Elasticsearch custom analyzer not workingElasticsearch 自定义分析器不工作
【发布时间】:2016-01-12 07:20:57
【问题描述】:

我使用 elasticsearch 作为我的搜索引擎,我现在正在尝试创建一个自定义分析器以使字段值小写。以下是我的代码:

创建索引和映射

create index with a custom analyzer named test_lowercase:

curl -XPUT 'localhost:9200/test/' -d '{
  "settings": {
    "analysis": {
      "analyzer": {
        "test_lowercase": {
          "type": "pattern",
          "pattern": "^.*$"
        }
      }
    }
  }
}'

create a mapping using the test_lowercase analyzer for the address field:

curl -XPUT 'localhost:9200/test/_mapping/Users' -d '{
  "Users": {
    "properties": {
      "name": {
        "type": "string"
      },
      "address": {
        "type": "string",
        "analyzer": "test_lowercase"
      }
    }
  }
}'

验证 test_lowercase 分析器是否工作:

curl -XGET 'localhost:9200/test/_analyze?analyzer=test_lowercase&pretty' -d '
Beijing China
'
{
  "tokens" : [ {
    "token" : "\nbeijing china\n",
    "start_offset" : 0,
    "end_offset" : 15,
    "type" : "word",
    "position" : 0
  } ]
}

正如我们所见,字符串 'Beijing China' 被索引为单个小写的整个术语 'beijing china',因此 test_lowercase 分析器可以正常工作。

验证“地址”字段是否使用小写分析器:

curl -XGET 'http://localhost:9200/test/_analyze?field=address&pretty' -d '
Beijing China
'
{
  "tokens" : [ {
    "token" : "\nbeijing china\n",
    "start_offset" : 0,
    "end_offset" : 15,
    "type" : "word",
    "position" : 0
  } ]
}
curl -XGET 'http://localhost:9200/test/_analyze?field=name&pretty' -d '
Beijing China
'
{
  "tokens" : [ {
    "token" : "beijing",
    "start_offset" : 1,
    "end_offset" : 8,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "china",
    "start_offset" : 9,
    "end_offset" : 14,
    "type" : "<ALPHANUM>",
    "position" : 1
  } ]
}

我们可以看到,对于同一个字符串 'Beijing China',如果我们使用 field=address 进行分析,它会创建一个 item 'beijing china',当使用 field=name 时,我们会得到两个 item 'beijing' 和'china',所以字段地址似乎使用了我的自定义分析器'test_lowercase'。

在测试索引中插入一个文档,看看分析器是否适用于文档

curl -XPUT 'localhost:9200/test/Users/12345?pretty' -d '{"name": "Jinshui Tang",  "address": "Beijing China"}'

很遗憾,文档已成功插入,但地址字段未正确分析。我无法通过使用通配符查询来搜索它,如下所示:

curl -XGET 'http://localhost:9200/test/Users/_search?pretty' -d '
{
  "query": {
    "wildcard": {
      "address": "*beijing ch*"
    }
  }
}'
{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

列出为文档分析的所有术语:

所以我运行以下命令查看文档的所有术语,我发现'Beijing China'根本不在术语向量中。

curl -XGET 'http://localhost:9200/test/Users/12345/_termvector?fields=*&pretty'
{
  "_index" : "test",
  "_type" : "Users",
  "_id" : "12345",
  "_version" : 3,
  "found" : true,
  "took" : 2,
  "term_vectors" : {
    "name" : {
      "field_statistics" : {
        "sum_doc_freq" : 2,
        "doc_count" : 1,
        "sum_ttf" : 2
      },
      "terms" : {
        "jinshui" : {
          "term_freq" : 1,
          "tokens" : [ {
            "position" : 0,
            "start_offset" : 0,
            "end_offset" : 7
          } ]
        },
        "tang" : {
          "term_freq" : 1,
          "tokens" : [ {
            "position" : 1,
            "start_offset" : 8,
            "end_offset" : 12
          } ]
        }
      }
    }
  }
}

我们可以看到名称被正确解析,变成了“jinshui”和“tang”两个词,但是地址丢失了。

有人可以帮忙吗?有什么遗漏吗?

非常感谢!

【问题讨论】:

    标签: elasticsearch analyzer


    【解决方案1】:

    要小写文本,您不需要pattern。使用这样的东西:

    PUT /test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "test_lowercase": {
              "type": "custom",
              "filter": [
                "lowercase"
              ],
              "tokenizer": "keyword"
            }
          }
        }
      }
    }
    
    PUT /test/_mapping/Users
    {
      "Users": {
        "properties": {
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "analyzer": "test_lowercase"
          }
        }
      }
    }
    
    PUT /test/Users/12345
    {"name": "Jinshui Tang",  "address": "Beijing China"}
    

    为了验证你做了正确的事,使用这个:

    GET /test/Users/_search
    {
      "fielddata_fields": ["name", "address"]
    }
    

    您将确切地看到 Elasticsearch 如何为您的数据编制索引:

            "fields": {
               "name": [
                  "jinshui",
                  "tang"
               ],
               "address": [
                  "beijing",
                  "china"
               ]
            }
    

    【讨论】:

    • 感谢安德烈·斯特凡。我需要小写,我需要地址的整个值是一个项目,而不是拆分成单词。例如,'Beijing China',我不想要 'beijing' 和 'china',相反,我想要一个词 'beijing china',以便用户可以使用通配符 '*jing chi*' 进行搜索。
    • 我更新了我的答案并将analyzerstandard 更改为keyword。试试看。
    • 谢谢安德烈,是的。你的代码对我有用,这正是我想要的。我会接受你的回答。但是你知道我的模式分析器有什么问题吗?
    • 模式分析器会根据特定模式拆分文本,是的,默认情况下它会将术语小写。该模式应与标记分隔符匹配。在您的情况下,没有这样的事情,因为您希望整个文本都匹配。在这种情况下,我认为模式应该是"pattern": "^"。但同样,这不是小写和保持文本完整的推荐方式。正则表达式的性能可能比我的建议差。
    • 完美,再次感谢!是的,关键字应该比正则表达式更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多