Использование анализатора в настраиваемом FieldBridge

У меня есть метод получения списка, который я хочу проиндексировать (токенизировать) в несколько полей.

У меня есть реализация FieldBridge, которая выполняет итерацию по списку и индексирует каждую строку в поле с индексом, добавленным к имени поля, чтобы дать каждому другому имя.

У меня есть две разные реализации анализатора (CaseSensitiveNGramAnalyzer и CaseInsensitiveNGramAnalyzer), которые я хочу использовать с этим FieldBridge (для создания индекса поля с учетом регистра и без учета регистра).

Это FieldBridge, к которому я хочу применить анализаторы:

public class StringListBridge implements FieldBridge
{

   @Override
   public void set(String name, Object value, Document luceneDocument, LuceneOptions luceneOptions)
   {
      List<String> strings = (List<String>) value;
      for (int i = 0; i < strings.size(); i++)
      {
         addStringField(name + 1, strings.get(i), luceneDocument, luceneOptions);
      }
   }

   private void addStringField(String fieldName, String fieldValue, Document luceneDocument, LuceneOptions luceneOptions)
   {
      Field field = new Field(fieldName, fieldValue, luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector());
      field.setBoost(luceneOptions.getBoost());
      luceneDocument.add(field);
   }
}
  • Можно ли применить анализатор к полю, в котором используется FieldBridge?
  • Если да, то можно ли это сделать с помощью аннотаций или нужно делать программно?
  • Если второе, могу ли я ввести анализатор в качестве параметра?

Я думаю о следующем, но совсем не знаком с потоками полевых токенов и т. Д .:

   private void addStringField(String fieldName, String fieldValue, Document luceneDocument, LuceneOptions luceneOptions)
   {
      Field field = new Field(fieldName, fieldValue, luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector());
      field.setBoost(luceneOptions.getBoost());
      try
      {
         field.setTokenStream(new CaseSensitiveNGramAnalyzer().reusableTokenStream(fieldName, new StringReader(fieldValue)));
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
      luceneDocument.add(field);
   }

Это разумный подход?

РЕДАКТИРОВАТЬ. Я попытался указать Analyzer и FieldBridge в аннотации @Field (без включения приведенного выше кода анализатора) следующим образом, но похоже, что он использует анализатор по умолчанию, а не те, которые указаны с помощью analyzer =.

   @Fields({
      @Field(name="content-nocase",
             index = Index.TOKENIZED,
             analyzer = @Analyzer(impl = CaseInsensitiveNgramAnalyzer.class),
             bridge = @FieldBridge(impl = StringListBridge.class)),
      @Field(name = "content-case",
             index = Index.TOKENIZED,
             analyzer = @Analyzer(impl = CaseSensitiveNgramAnalyzer.class),
             bridge = @FieldBridge(impl = StringListBridge.class)),
   })
   public List<String> getContents()

person David Mason    schedule 12.04.2012    source источник


Ответы (2)


Атм решения - через анализатор с настраиваемой областью действия или использование @AnalyzerDiscriminator вместе с @AnalyzerDef. Это также обсуждается на форуме поиска Hibernate - https://forum.hibernate.org/viewtopic.php?f=9&t=1016667

person Hardy    schedule 05.07.2012

Мне удалось заставить это работать. Поиск в спящем режиме, похоже, не использует указанный анализатор, если указаны как analyzer =, так и bridge =, по крайней мере, если указанный мост создает несколько полей.

Ручная передача TokenStream от желаемого анализатора к сгенерированным полям в мосту дала мне ожидаемый результат:

   private void addStringField(String fieldName, String fieldValue, Document luceneDocument, LuceneOptions luceneOptions)
   {
      Field field = new Field(fieldName, fieldValue, luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector());
      field.setBoost(luceneOptions.getBoost());

      // manually apply token stream from analyzer, as hibernate search does not
      // apply the specified analyzer properly
      try
      {
         field.setTokenStream(analyzer.reusableTokenStream(fieldName, new StringReader(fieldValue)));
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
      luceneDocument.add(field);
   }

ParameterizedBridge реализован, чтобы указать, какой анализатор использовать (экземпляр analyzer создается и сохраняется в поле до вызова этого метода).

person David Mason    schedule 13.04.2012
comment
Могу я спросить, как вы создаете анализаторы. Программно или вы нашли способ получить доступ по имени к тем, которые созданы с помощью @AnalyzerDef? - person HandyManDan; 05.04.2014
comment
@HandyManDan Я давно не касался этого, но похоже, что в конце концов я создал их вручную. Вот соответствующая фиксация, когда я работал над этим, вероятно, есть соответствующая информация в окружающих коммитах и, возможно, в текущих версиях измененных файлов (хотя наша индексация несколько изменилась за последний год): github.com/zanata/zanata-server/commit/ - person David Mason; 07.04.2014
comment
Спасибо за подтверждение. Я считаю, что в настоящее время нет возможности получить доступ к именованному анализатору, созданному с помощью AnalyzerDef, внутри реализации моста. Эта проблема решает hibernate.atlassian.net/browse/HSEARCH-1306. - person HandyManDan; 08.04.2014