簡體   English   中英

NHibernate搜索和IList的Lucene初始索引

[英]NHibernate Search and Lucene initial indexing of IList

我在使用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)]

在標記要索引的實體之后,我必須對1200萬行進行初始索引(使用批處理)。 在我開始索引名為BookAdditionalInfos的IList之前,一切工作都是完美的。 如果沒有這個IndexedEmbedded屬性(或者沒有為這個IList編制索引),一切都會好起來的,並且每個帶有Field屬性的屬性標記都將被建立索引。

我正在使用Fluent NHibernate。

有什么問題嗎?

謝謝

編輯 :我也看了http://ayende.com/blog/3992/nhibernate-search ,但沒有任何結果

問題是:當我嘗試對IList進行索引時,索引將永遠占用,並且不會對任何內容進行索引。 不對這個IList進行索引(或不對IList指定IndexedEmbedded),索引就可以了,並且得到了索引結果。

編輯(初始索引功能):

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

在我看來,您在那兒遇到了經典的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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM