【问题标题】:SOLR and accented charactersSOLR 和重音字符
【发布时间】:2017-04-20 20:14:52
【问题描述】:

我有一个职业索引(标识符+职业):

<field name="occ_id" type="int" indexed="true" stored="true" required="true" />
<field name="occ_tx_name" type="text_es" indexed="true" stored="true" multiValued="false" />


<!-- Spanish -->
<fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
  <analyzer> 
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" />
    <filter class="solr.SpanishLightStemFilterFactory"/>
  </analyzer>
</fieldType>

这是一个真实的查询,针对三个标识符(1、195 和 129):

curl -X GET "http://192.168.1.11:8983/solr/cyp_occupations/select?indent=on&q=occ_id:1+occ_id:195+occ_id:129&wt=json"
{
  "responseHeader":{
    "status":0,
    "QTime":1,
    "params":{
      "q":"occ_id:1 occ_id:195 occ_id:129",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound":3,"start":0,"docs":[
      {
        "occ_id":1,
        "occ_tx_name":"Abogado",
        "_version_":1565225103805906944},
      {
        "occ_id":129,
        "occ_tx_name":"Informático",
        "_version_":1565225103843655680},
      {
        "occ_id":195,
        "occ_tx_name":"Osteópata",
        "_version_":1565225103858335746}]
  }}

其中两个有重音字符,一个没有。因此,让我们不使用重音符号按 occ_tx_name 进行搜索:

curl -X GET "http://192.168.1.11:8983/solr/cyp_occupations/select?indent=on&q=occ_tx_name:abogado&wt=json"
{
  "responseHeader":{
    "status":0,
    "QTime":1,
    "params":{
      "q":"occ_tx_name:abogado",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "occ_id":1,
        "occ_tx_name":"Abogado",
        "_version_":1565225103805906944}]
  }}

curl -X GET "http://192.168.1.11:8983/solr/cyp_occupations/select?indent=on&q=occ_tx_name:informatico&wt=json"
{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"occ_tx_name:informatico",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound”:1,”start":0,"docs":[
      {
        "occ_id":129,
        "occ_tx_name":"Informático",
        "_version_":1565225103843655680}]
  }}


curl -X GET "http://192.168.1.11:8983/solr/cyp_occupations/select?indent=on&q=occ_tx_name:osteopata&wt=json"
{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"occ_tx_name:osteopata",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound":0,"start":0,"docs":[]
  }}

我对最后一次搜索“osteopata”失败而“informatico”成功的事实感到非常恼火。索引的源数据是一个简单的 MySQL 表:

-- -----------------------------------------------------
-- Table `mydb`.`occ_occupation`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`occ_occupation` (
  `occ_id` INT UNSIGNED NOT NULL,
  `occ_tx_name` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`occ_id`)
ENGINE = InnoDB

表格的排序规则是“utf8mb4_general_ci”。索引是使用 DataImportHandler 创建的。这是定义:

<dataConfig>
    <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.1.11:3306/mydb"
        user=“mydb” password=“mydb” />
    <document name="occupations">
        <entity name="occupation" pk="occ_id"
            query="SELECT occ.occ_id, occ.occ_tx_name FROM occ_occupation occ WHERE occ.sta_bo_deleted = false">
            <field column="occ_id" name="occ_id" />
            <field column="occ_tx_name" name="occ_tx_name" />
        </entity>
    </document>
</dataConfig> 

我需要一些线索来检测问题。谁能帮我?提前致谢。

【问题讨论】:

  • 我忘了提到我正在使用 solr-6.3.0,并且我正在使用以下命令启动服务器: solr start -a "-Duser.language=es -Duser.country= ES -Duser.timezone=欧洲/马德里"

标签: solr accent-insensitive


【解决方案1】:

只需将solr.ASCIIFoldingFilterFactory 添加到您的过滤器分析器链中,或者更好地创建一个新的 fieldType:

<!-- Spanish -->
<fieldType name="text_es_ascii_folding" class="solr.TextField" positionIncrementGap="100">
  <analyzer> 
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.ASCIIFoldingFilterFactory" />
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" />
    <filter class="solr.SpanishLightStemFilterFactory"/>
  </analyzer>
</fieldType>

此过滤器转换字母、数字和符号 Unicode 不在基本拉丁语 Unicode 块中的字符(第一个 127 个 ASCII 字符)到它们的 ASCII 等价物(如果存在)。

即使重音字符丢失,这也应该让您匹配搜索。 缺点是“cañon”和“canon”之类的词现在是等价的,并且都命中了相同的文件 IIRC。

【讨论】:

  • 嗨。我添加了过滤器“solr.ASCIIFoldingFilterFactory”,但得到完全相同的结果...
  • 你必须重新索引整个集合
【解决方案2】:

我认为 mysql 或您的 jvm 设置与此无关。我怀疑一个有效,另一个可能不是由于 SpanishLightStemFilterFactory。

无论变音符号如何,实现匹配的正确方法是使用以下内容:

  <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>

将它放在索引和查询分析器链中的标记器之前,并且任何变音符号都应转换为 ascii 版本。这将使它始终有效。

【讨论】:

  • 转到分析选项卡,在机器人索引和查询端查看该单词的详细输出
  • 太疯狂了!在 Solr Admin 中,我选择了我的索引,然后单击了 Schema 部分。然后,我选择了“occ_tx_name”字段,然后是“加载术语信息”按钮,这样我就可以看到列出的前 10 个术语。我已将 10 更改为 278,以查看所有术语。列表中的每个术语都是一个 HTML Anchor,它链接到 SOLR 查询。而且,我不敢相信我看到...
  • 在列表中,所有术语都有重音字符...除了“informatico”!我会给你一个例子。这是与存储的术语“informatico”(没有重音字符的小写字母)关联的锚点:informatico
  • 这是与“osteópata”关联的锚点:osteópata... 如您所见,“osteópata”有以 de 重音字符存储....我不知道为什么,但此搜索成功: curl -X GET "192.168.1.11:8983/solr/cyp_occupations/…"
  • 您在更改架构以添加 charfilter 后重新索引了吗??
【解决方案3】:

好的,我发现了源问题。我已经用 VI 以十六进制模式打开了我的 SQL 加载脚本。

这是 INSERT 语句中“Agrónomo”的十六进制内容:41 67 72 6f cc 81 6e 6f 6d 6f。

6f cc 81!!!! This is "o COMBINING ACUTE ACCENT" UTF code!!!!

这就是问题所在......它必须是“c3 b3”......我从网页上复制/粘贴文字,所以来源上的源字符是问题。

谢谢你们,因为我对SOLR的灵魂有了更多的了解。

问候。

【讨论】:

    猜你喜欢
    • 2012-11-08
    • 2021-12-02
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 2023-03-03
    相关资源
    最近更新 更多