Copied to clipboard

Flag this post as spam?

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


These support forums are now closed for new topics and comments.
Please head on over to http://eureka.ucommerce.net/ for support.

  • Bo Damgaard Mortensen 719 posts 1207 karma points
    Jan 04, 2013 @ 12:43
    Bo Damgaard Mortensen
    0

    Product rendering and performance ponderings

    Hi all,

    I'm trying to make a razor macro which renders X focus products on the frontpage. However, if the admin haven't set any products as focusproduct, it should just render three random products, downscaling to: if administrator has selected one or two products as focusproducts, it should thus render two or a single product(s)

    My razor file looks like this:

    @* This macro renders the focus products on the frontpage *@
    @using UCommerce.EntitiesV2
    @using UCommerce.Extensions
    @using UCommerce.Api
    
    @{
        // Get focus products
        var focusProducts = new List<Product>();
        var allProducts = Product.All().Where(x => x.DisplayOnSite);    
        int takeCount = 3;
    
        <ul class="thumbnails focus-products">
            @* Get all focus products *@
            @foreach(var product in allProducts)
            {
                if(product.DisplayOnSite && product.GetProperty("Fokusprodukt") != null && Convert.ToBoolean(product.GetProperty("Fokusprodukt").GetValue()))
                {
                    focusProducts.Add(product);                      
                }
            }
    
            @* Check if there was any focus products *@
            @if(focusProducts.Count > 0)
            {
                // Render focus products
                @RenderFocusProducts(focusProducts)
    
                // Check if the number of focus products are less than three
                if(focusProducts.Count < 3)
                {                
                    // Calculate new take count to render rest of the focus products as random products
                    takeCount = takeCount - focusProducts.Count;
    
                    // Render the rest as random products so there's always three products on the frontpage
                    @RenderRandomProducts(takeCount, allProducts, focusProducts)
                }                            
            }
            else
            {
                // No focus products found. Render three random products
                @RenderRandomProducts(takeCount, allProducts, focusProducts)
            }
        </ul>
    }
    
    @helper RenderFocusProducts(List<Product> products)
    {
        foreach (var product in products)
        {
            <li class="span4">
                <a href="@CatalogLibrary.GetNiceUrlForProduct(product)">
                    <div class="thumbnail">
                        <div class="image"><img src="@Model.MediaById(product.PrimaryImageMediaId).umbracoFile" alt=""></div>
                        <h3>@product.Name</h3>                  
                        <p>
                            @product.GetProperty("Teaser").GetValue() 
                        </p>          
                    </div>
                </a>
            </li>          
        }
    }
    
    @helper RenderRandomProducts(int takeCount, IQueryable<Product> products, List<Product> focusProducts)
    {
        // Pick three random products which are not marked as focus products
        var rnd = new Random();
        var randomProducts = products.ToList().OrderBy(x => rnd.Next()).Where(x => !focusProducts.Contains(x)).Take(takeCount);
    
        foreach (var product in randomProducts)
        {
            <li class="span4">
                <a href="@CatalogLibrary.GetNiceUrlForProduct(product)">
                    <div class="thumbnail">
                        <div class="image"><img src="@Model.MediaById(product.PrimaryImageMediaId).umbracoFile" alt=""></div>
                        <h3>@product.Name</h3>                  
                        <p>
                            @product.GetProperty("Teaser").GetValue() 
                        </p>          
                    </div>
                </a>
            </li> 
        }
    }

    What I'm concerned about here is performance, since I basically start by pulling all the products from the database to find the products marked with "Fokusprodukt" (Focusproduct) and work my way from there.

    Was wondering if there was a more performant method than this I may have missed? :-)

    Thanks a lot in advance.

    All the best,

    Bo

  • Nickolaj Lundgreen 233 posts 1132 karma points
    Jan 07, 2013 @ 11:24
    Nickolaj Lundgreen
    0

    I would use a category to hold the focus product (make a new category definitions and filter it from the navigation and other places where you would display categories).

    It would also be easier to maintain when you have a list of products in the backend and it should perform a lot better.

    So something like:

     

    var focusCategory = Category.FirstOrDefault(x => x.Definition.Name == "XXX");
        if(focusCategory.Products.Any())
        {
            //Grab some products here
        }
        else
        {
            //Pick some random products here
        }
  • Søren Spelling Lund 1797 posts 2786 karma points
    Jan 09, 2013 @ 11:23
    Søren Spelling Lund
    100

    Hi Bo,

    What you want to do is make sure that you leave the work of selecting randon products to the database.

    Doing it as pure SQL looks like this:

    SELECT productId FROM uCommerce_Product ORDER BY NEWID()

    The trick then become to do the same via the uCommerce query API.

    You can to go a little deep in the query API and use HQL to get the best performance:

    IList<Product> randomProducts;
    var sessionProvider = ObjectFactory.Instance.Resolve<ISessionProvider>();
    using (var session in sessionProvider.GetSession())
    {
    randomProducts = session
    .CreateQuery("FROM Product p WHERE p.ParentProduct IS NULL ORDER BY NEWID()") // random ordering with NEWID() .SetMaxResults(3) // Limit to three products .List<Product>(); // Execute the query
    }

    Not too bad :)

    I took the liberty to only ask for products and product families filtering variants from the result.

    Hope this helps.

  • Bo Damgaard Mortensen 719 posts 1207 karma points
    Jan 15, 2013 @ 15:59
    Bo Damgaard Mortensen
    0

    Nikolaj: Thanks a lot! Good solution, but the customer didn't want to maintain a separate category for the focus products :-/

    Søren: Fantastic! That's exactly what I was looking for :-) Thanks so much.

Please Sign in or register to post replies

Write your reply to:

Draft