Search code examples
c#asp.netasp.net-mvcasp.net-mvc-4rating

Display items based on ratings MVC


I have a Product table with columns "ProductId(pk), P_Name, Price, Quantity"

and another table VoteLogs with columns "V_id(pk), ProductId, UserId, Vote"

I've implemented the rating feature by following this tutorial

The Vote Log table contains the following data

VoteLog Table Data

As you can see [email protected] and [email protected] both voted product 28 but [email protected] has also voted product 20, 72, 1187, and 1188

Now when [email protected] log in, I want to display him product 20, 72, 1187, 1188 because customer1 and customer2 both voted the same product so they might have similar taste.

I have tried and came this far,

public ActionResult BasedOnRating()
    {
        string UserId = User.Identity.GetUserName(); //logged in with [email protected]
        var query = from vv in db.VoteLogs
                    join pp in db.Products
                    on vv.ProductId equals pp.ProductId
                    where !(db.VoteLogs.Where(c => c.UserName == UserId)
                           .Select(c => c.Product.ProductId).ToList())
                           .Contains(vv.Product.ProductId) && (vv.UserName == "[email protected]")
                    select pp;

        return View(query);
    }

and I get the desired result:

Result of query

But I don't want to write [email protected] in the query, What If i have 1000+ users. I guess here I should pass the list of users who has voted the same products. I'm confused here. I would appreciate any help. Thanks


Solution

  • To break this down into its individual components

    First you need to get the ID's of the products the current user has voted on

    string UserId = User.Identity.GetUserName();
    var userProducts = db.VoteLogs.Where(v => v.UserName == userId).Select(v => v.ProductId);
    

    Then get all the other users who have also voted for one of those products

    var likeUsers = db.VoteLogs.Where(v => userProducts.Contains(v.ProductId) && v.UserName != userId).Select(v => v.UserName);
    

    Then get all other products that those users have voted on

    var likeProducts = db.VoteLogs.Where(v => likeUsers.Contains(v.UserName)).Select(v => v.ProductId).Except(userProducts);
    

    And finally return those products

    return View(db.Products.Where(p => likeProducts.Contains(p.ID)));
    

    Based on the table you have shown, this will return products 20, 72, 1187 and 1188. If you were to add another row to your votes table with ProductId = 109 and UserName = "[email protected]" then the results will be 19, 20, 30, 72, 1111, 1187 and 1188.

    Note that since you have potentially thousands of users and products, this could return thousands of products to the view, so you may want to consider limiting the results, for example you might order the likeProducts query by Vote (highest) and take only the top #.