SOLR и акцентированные персонажи

У меня есть индекс для профессий (идентификатор + род занятий):

<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> 

Мне нужна подсказка, чтобы обнаружить проблему. Может кто-нибудь мне помочь? Заранее спасибо.

3 ответа

Решение

Хорошо, я обнаружил проблему с источником. Я открыл свой скрипт загрузки SQL с помощью VI в шестнадцатеричном режиме.

Это шестнадцатеричное содержание для Agrónomo в операторе INSERT: 41 67 72 6f cc 81 6e 6f 6d 6f.

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

Так вот в чем проблема... Это должно быть "c3 b3"... Я получаю копии / вставки литералов с веб-страницы, поэтому проблема с исходными символами в источнике.

Спасибо вам обоим, потому что я узнал больше о душе SOLR.

С уважением.

Просто добавь 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 (первые 127 символов ASCII), в их эквиваленты ASCII, если таковые существуют.

Это должно позволить вам соответствовать поиску, даже если акцентированный символ отсутствует. Недостатком является то, что такие слова, как "канон" и "канон", теперь эквивалентны, и оба слова попадают в одни и те же документы IIRC.

Я не думаю, что mysql или ваши настройки jvm как-то связаны с этим. Я подозреваю, что один работает, а другой нет, вероятно, из-за SpanishLightStemFilterFactory.

Правильный способ достижения соответствия независимо от диакритических знаков заключается в использовании следующего:

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

Поместите это перед вашим токенизатором в цепочках анализатора индекса и запроса, и любой диакритический знак должен быть преобразован в версию ascii. Это сделало бы это работать всегда.

Другие вопросы по тегам