Question

I'm using NHibernate Search for NHibernate 3.0 GA.

I have this code in my product repository:

public IList<Product> Find(string term)
        {
            var productFields = new[] { "Name", "Description" };
            var importance = new Dictionary<String, float>(2) { { "Name", 4 }, { "Description", 1 } };
            var analyzer = new StandardAnalyzer();
            var parser = new MultiFieldQueryParser(
                productFields,
                analyzer,
                importance);

            var query = parser.Parse(term);

            var session = Search.CreateFullTextSession(NHibernateSession.Current);
            var tx = session.BeginTransaction();
            var fullTextQuery = session.CreateFullTextQuery(query);
            fullTextQuery.SetFirstResult(0).SetMaxResults(20);
            var results = fullTextQuery.List<Product>();
            tx.Commit();

            return results;
        }

In NH Profiler, I can see that a select statement is issued for every product found. What am I missing?

I found this thread from 2009 but presumably this bug has been fixed.

EDIT [06/06/2011]:

My property mappings as far as associations go are as follows:

mapping.HasManyToMany(c => c.Categories)
                .Table("CatalogHierarchy")
                .ParentKeyColumn("child_oid")
                .ChildKeyColumn("oid")
                .Cascade.None()
                .Inverse()
                .LazyLoad()
                .AsSet();

            mapping.HasMany(c => c.Variants)
                .Table("CatalogProducts")
                .Where("i_ClassType=2")
                .KeyColumn("ParentOID")
                .Cascade.SaveUpdate()
                .AsSet();

I don't really want to eager fetch all categories.

Was it helpful?

Solution 3

I solved this in the end. I realised I had not wrapped the whole thing into a transaction. Once I did, the N+1 issue was gone. Schoolboy error, but hey, you learn by your mistakes.

OTHER TIPS

As NHibernate.Search is unstable, I would use (and I did) Lucene.NET directly from my application - just to ask Lucene for objects' Ids and then load it using Session.Load().

Also you could change LazyLoad settings at class mapping level, not at relationship level. Hope it helps.

EDIT: you could specify batch-size for relationships, so they wouldn't cause select N+1 problem

Are you referencing any lazy loaded properties in the product list that is returned by this method? If so, you can change the property mapping to "eager fetch".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top