0

Lucene を使用して IList のインデックスを作成するという退屈な問題があり、修正できません。

私のエンティティには、次のように IndexedEmbedded 属性を適用する IList が含まれています。

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

1 に答える 1

0

そこには古典的なN + 1選択の問題があるように見えます-基本的に、本を選択するとき、BookAdditionalInfoも選択していないため、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();
于 2012-05-20T09:41:52.413 に答える