2012-05-03 2 views
0

У меня есть некоторая скучная проблема индексации IList с использованием Lucene, и я не могу исправить.Поиск NHibernate и начальная индексация Lucene IList

Мой объект содержит IList, который я применить IndexedEmbedded атрибута, как это:

[ScriptIgnore] //will not serialize 
[IndexedEmbedded(Depth = 1, Prefix = "BookAdditionalInfos_"] 
public virtual IList<BookAdditionalInfo> BookAdditionalInfos { get; set; } 

Кроме того, некоторые другие свойства, используемые атрибуты Field для индексирования:

[Field(Index.Tokenized, Store = Store.Yes)] 

После маркировки объекта для индексации, я должен сделать начальную индексацию 12 миллионов строк (с использованием пакетной обработки). И все работает идеально, пока я не начну индексировать IList под названием BookAdditionalInfos. Без этого атрибута IndexedEmbedded (или без индексации этого IList) все в порядке, и каждый знак свойства с атрибутом Field будет проиндексирован.

Я использую Fluent NHibernate.

В чем может быть проблема?

Спасибо

EDIT: Кроме того, я посмотрел на http://ayende.com/blog/3992/nhibernate-search, но без каких-либо результатов

Проблема: когда я пытаюсь указательным IList, индексирование принимает навсегда, и ничто не будет индексироваться. Без индексации этого IList (или без указания IndexedEmbedded to IList) индексирование в порядке, и я получил индексированные результаты.

EDIT (начальная функция Indexing):

public void BuildInitialBookSearchIndex() 
     { 
      FSDirectory directory = null; 
      IndexWriter writer = null; 

      var type = typeof(Book); 

      var info = new DirectoryInfo(GetIndexDirectory()); 

      //if (info.Exists) 
      //{ 
      // info.Delete(true); 
      //} 

      try 
      { 
       directory = FSDirectory.GetDirectory(Path.Combine(info.FullName, type.Name), true); 
       writer = new IndexWriter(directory, new StandardAnalyzer(), true); 
      } 
      finally 
      { 
       if (directory != null) 
       { 
        directory.Close(); 
       } 

       if (writer != null) 
       { 
        writer.Close(); 
       } 
      } 

      var fullTextSession = Search.CreateFullTextSession(Session); 

      var currentIndex = 0; 
      const int batchSize = 5000; 

      while (true) 
      { 
       var entities = Session 
        .CreateCriteria<Book>() 
        .SetFirstResult(currentIndex) 
        .SetMaxResults(batchSize) 
        .List(); 

       using (var tx = Session.BeginTransaction()) 
       { 
        foreach (var entity in entities) 
        { 
         fullTextSession.Index(entity); 
        } 

        currentIndex += batchSize; 

        Session.Flush(); 
        tx.Commit(); 
        Session.Clear(); 
       } 

       if (entities.Count < batchSize) 
        break; 
      } 
     } 
+0

В чем проблема? есть ли исключение? –

+0

не генерирует исключения. Исходная функция индексации, которую я использую для индексирования 12 миллионов строк, задана выше. Я предполагаю, что есть некоторая проблема с этой функцией, когда IList отмечен как IndexedEmbedded – Koste

+1

Я смущен, когда вы говорите проблему, что вы имеете в виду, никакое исключение не выбрасывается, ОК. Это навсегда? неправильно ли оно индексирует поле? – Prescott

ответ

0

Он смотрит на меня, как у вас есть классический N + 1 выберите проблему там - в основном, когда вы выбираете ваши книги, вы а также не выбирать BookAdditionalInfos, поэтому NHibernate должен будет выпустить новый выбор для каждой книги для извлечения BookAdditionalInfo для этой книги при индексировании. Быстрое исправление было бы изменить ваш выбор, чтобы:

var entities = Session 
       .CreateCriteria<Book>() 
       .SetFetchMode("BookAdditionalInfos", FetchMode.Eager) 
       .SetResultTransformer(Transformers.DistinctRootEntity) 
       .SetFirstResult(currentIndex) 
       .SetMaxResults(batchSize) 
       .List(); 

Вы, вероятно, столкнетесь с дополнительными проблемами с вашей пейджинговой компанией, однако, потому что он будет делать объединение на стол BookAdditionalInfo давая вам несколько строк для одной и той же сущности в вашем результирующем наборе, чтобы вы могли посмотреть на что-то вроде:

var pagedEntities = DetachedCriteria.For<Book>() 
       .SetFirstResult(currentIndex) 
       .SetMaxResults(batchSize) 
       .SetProjection(Projections.Id()); 

    var entities = Session 
       .CreateCriteria<Book>() 
       .Add(Property.ForName("id").In(pagedEntities)) 
       .SetFetchMode("BookAdditionalInfos", FetchMode.Eager) 
       .SetResultTransformer(Transformers.DistinctRootEntity) 
       .List(); 
+0

Мартин, спасибо за ваш ответ. Я пробую это решение, но без каких-либо результатов. Я также пытаюсь получить BookAdditionalInfos, но он не индексировал. Ни одна из книг не индексируется, если общий список отмечен как IndexedEmbedded. Я сделал обходной путь, я проиндексировал класс BookAdditionalInfo, где я держу ссылку на объект Book и mark Book как IndexedEmbedded, и все в порядке. Спасибо за второе предложение. – Koste

Смежные вопросы