Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Chris Foot 61 posts 93 karma points
    Mar 05, 2015 @ 12:59
    Chris Foot
    1

    Searching for products by partial sku and getting IPublishedContent back

    I have a site which has ~3k products and I have to do a search page for the front end. Can anyone recommend the best way to get a list of IPublishedContents back from a partial sku. My current (clearly very wrong) approach looks like this:

    var products = Umbraco.TypedContent(10451).Descendants("Product").Where(y => y.GetPropertyValue<ProductDisplay>("product").Sku.Contains(table.searchTerms));
    

    Is there a performant way to link my product documents to the merchello products? Unfortunately I need to get the documents back as I have to display many fields from the product document and I also need to merge the results that come back with a search on the name field for the product documents.

    Thanks

    Chris

  • Carsten Fallesen 35 posts 154 karma points
    Mar 05, 2015 @ 13:05
    Carsten Fallesen
    0

    Hi Chris,

    I faced the same challenge when I built my first Mechello shop. I solved that using a customize Examine index. 

    I added all the necessary information from Merchello on a customized version of the standad External index. All category displays the get the display information from the Examine index.

    Using this approach gave me the speed and flexibility of Examine with a little added logic.

    if you are interested in this approach I can give you some pointers on the code.

    Carsten

  • Chris Foot 61 posts 93 karma points
    Mar 05, 2015 @ 14:06
    Chris Foot
    0

    Yes please! I had a look at examine but I couldn't work out how to get the merchello products linked with the umbraco document.

    Thanks

    Chris

  • Carsten Fallesen 35 posts 154 karma points
    Mar 05, 2015 @ 15:48
    Carsten Fallesen
    2

    I have tried to strip down the code I use to update the index:

        public class AppStarting : IApplicationEventHandler

        {

            private static readonly object s_LockObj = new object();

            private static bool s_Ran;

     

            public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)

            {

                if (s_Ran)

                    return;

     

                lock (s_LockObj)

                {

                    if (s_Ran)

                        return;

                    //Add event to allow searching by site section

                    var indexerSite = ExamineManager.Instance.IndexProviderCollection["ExternalIndexer"];

                    indexerSite.GatheringNodeData += this.SetSiteSearchFields;

                    var productIndexerSite = ExamineManager.Instance.IndexProviderCollection["MerchelloProductIndexer"];

                    productIndexerSite.GatheringNodeData += this.SetProductSearchFields;

     

                    s_Ran = true;

                }

            }

     

            private void SetProductSearchFields(object sender, IndexingNodeDataEventArgs e)

            {

                // Find documents referencing product

                var sku = e.Fields.ContainsKey("productKey") ? e.Fields["productKey"] : null;

                if (sku != null)

                {

                    BaseSearchProvider searcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];

                    ISearchCriteria criteria = searcher.CreateSearchCriteria(IndexTypes.Content);

                    IBooleanOperation query = criteria.NodeTypeAlias("ShopProduct");

                    query = query.And().GroupedOr(new[] { "product" }, sku);

     

                    var compiledQuery = query.Compile();

                    ISearchResults productRowsRaw = searcher.Search(compiledQuery);

     

                    foreach (var result in productRowsRaw)

                    {

                        ExamineManager.Instance.ReIndexNode(new Document(result.Id).ToXDocument(false).Root, IndexTypes.Content);

                    }

                }

            }

     

            private void SetSiteSearchFields(object sender, IndexingNodeDataEventArgs e)

            {

                //grab the current data from the Fields collection

                var path = e.Fields["path"];

     

                //let's get rid of those commas!

                path = path.Replace(",", " ");

     

                //add as new field, as path seems to be a reserved word in Lucene

                e.Fields.Add("searchPath", path);

     

                if (e.Fields.ContainsKey("product"))

                {

                    var productString = e.Fields["product"];

                    if (!String.IsNullOrEmpty(productString))

                    {

                        var productGuid = new Guid(productString);

                        var productVariants = Merchello.Core.MerchelloContext.Current.Services.ProductService.GetProductVariantsByProductKey(productGuid).Where(x => x.Available).ToList();

                        if (productVariants.Any())

                        {

                            var minPrice = productVariants.Min(x => x.Price);

                            var minSalePrice = productVariants.Min(x => x.SalePrice) ?? minPrice;

                            var manufacturer = productVariants.Max(x => x.Manufacturer);

                            string modelNumbers = "";

                            string skus = "";

                            foreach (var productVariant in productVariants)

                            {

                                modelNumbers += productVariant.ManufacturerModelNumber + " ";

                                skus += productVariant.Sku + " ";

                            }

                            e.Fields.Add("price", minPrice.ToString("00000"));

                            e.Fields.Add("salePrice", minSalePrice.ToString("00000"));

                            e.Fields.Add("manufacturer", manufacturer);

                            e.Fields.Add("onSale", productVariants.Any(x => x.OnSale).ToString());

                            e.Fields.Add("modelNumbers", modelNumbers);

                            e.Fields.Add("sku", skus);

                        }

                    }

                }

            }

        }

    I know there is a lot of code here, but basically it consists of two parts. The SetProductSearchFields method ensures that the nodes referencing the product is reindexed when a product is updated in Merchello. The SetSiteSearchFields method adds the product fields needed for rendering.

    I removed some code to reduce complexity, so the code might not work as is. Just ask if you have any questions.

    Carsten

  • Joe 32 posts 136 karma points
    Sep 28, 2018 @ 20:49
    Joe
    0

    Just want to add 1 point. In my case, I need to further specify the type (ProductIndexer). i.e.

    var productIndexerSite = (ProductIndexer)ExamineManager.Instance.IndexProviderCollection["MerchelloProductIndexer"];
    

    Otherwise the

    productIndexerSite.GatheringNodeData += this.SetProductSearchFields;
    

    doesn't work. I'm not sure why actually but it's what I did as fix.

  • Chris Foot 61 posts 93 karma points
    Mar 05, 2015 @ 17:57
    Chris Foot
    0

    Hi Carsten,

    That looks great. I have it compiling in my project. Just trying to get my head around how to actually use examine to do the search now! I'll let you know if I get stuck.

    Thanks

    Chris

  • Chris Foot 61 posts 93 karma points
    Mar 06, 2015 @ 18:09
    Chris Foot
    1

    Hi Carten,

    Thank you for your code. I have it working perfectly with very little tweaking.

    Thanks

    Chris

  • PierreD Savard 183 posts 290 karma points
    May 27, 2015 @ 02:22
    PierreD Savard
    0

    I have a question. I use your code and this line never return any variants:

    var productVariants = Merchello.Core.MerchelloContext.Current.Services.ProductService.GetProductVariantsByProductKey(productGuid).Where(x => x.Available).ToList();
    

    But in my merchello product I add SKU, Manufacturer, UPC code, Manufacturer MOdel No.

    Can you also paste a line code of how to do the search in my controller, for example get all manufacturers. ?

    Thanks

  • Joe 32 posts 136 karma points
    Sep 28, 2018 @ 20:57
    Joe
    0

    I faced the same problem, it seems those keys are indexed but not searchable. My dirty workaround is:

    Basing on the GatheringNodeData handler provided by Carsten, just add the field you want to search. e.g.

    e.Fields.Add("sku_searchable", e.Fields["sku"]);
    

    Then I also identified these extra fields as user fields, so you just search on these searchable index clone instead of the original one.

    I want to add one more points, e.g. original "price" & "salesPrice" fields are not assigned with correct type, thus failing the "Range" LuceneQuery. To fix it, I overrided their type to DOUBLE

Please Sign in or register to post replies

Write your reply to:

Draft