Reputation: 1026
I have a Items
table and ItemVotes
table that every user can give Up vote or Down vote to an item and his/her vote determine by a bool
property in ItemVotes
table. Now I want to have a list of Items
order by votes, for do this we need to get count of true
votes minus count of false
votes.
_ItemsService.GetAll(x => x.ItemVotes //here I have to order by vote)
UPDATE :
Items Entity:
public class Items : Entity<int>
{
public int UserId { get; set; }
public DateTime Date { get; set; }
public string Subject { get; set; }
public virtual ICollection<ItemVotes> ItemVotes { get; set; }
}
ItemVotes Entity:
public class ItemVotes : Entity<int>
{
public int ItemId { get; set; }
public int UserId { get; set; }
public DateTime Date { get; set; }
public bool TypeVote { get; set; }
public virtual Items Items { get; set; }
public virtual Users Users { get; set; }
}
UPDATE 2:
I use Gilad Green's answer in an action like this:
public ActionResult TopItems()
{
var items = _ItemsService.GetAllQuerable(x => x)
.OrderBy(item => item.ItemsVote.Sum(vote => vote.TypeVote ? 1 : -1));
return View(items);
}
And here is GetAllQuerable()
function :
public IEnumerable<T> GetAllQuerable(
Expression<Func<T,
bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "")
{
return _repository.GetAllQuerable(filter, orderBy, includeProperties);
}
Upvotes: 0
Views: 183
Reputation: 37281
To achieve I want to have a list of Items order by votes first retrieve all items and then order them by the described logic:
retrievedItems.OrderBy(item => item.ItemVotes.Sum(vote => vote.TypeVote ? 1 : -1));
In your current code of _ItemsService.GetAll(x => x.ItemVotes)...
you lose the scope of knowing which vote belongs to which item and hence will get a single summary for all items together
Upvotes: 1
Reputation: 41
You need to do the following in order to get a sorted list of items based on their votes with most positive voted items first.
Expose a method GetOrderedItems in your _ItemsService which will perform all the logic and return you the desired result instead of running your logic inside the caller to this service.
GetOrderedItems(Func<bool,int> predicate)
{
return items.OrderByDescending(p => p.ItemVotes.Select(x => x.TypeVote).Sum(predicate)).ToList();
}
In your call to the service you can pass in the selector like this:
Func<bool, int> getPositiveVotedItemsFirst = (vote) => vote ? 1 : -1;
var itemsOrderedByPositiveVotes = _ItemsService.GetOrderedItems(getHighlyVotedItems);
You could now easily get the items ordered by the least voted ones , just by changing your selector.
Func<bool, int> getLeastVotedItemsFirst = (vote) => !vote ? 1 : -1;
var itemsOrderedByNegativeVotes = _ItemsService.GetOrderedItems(getLeastVotedItemsFirst);
Upvotes: 0
Reputation: 76988
Let's suppose you have a variable foo
where you have the items, then:
bar = foo.OrderBy(item => item.ItemVotes.Sum(vote => vote.TypeVote ? 1 : -1));
Upvotes: 0
Reputation: 5520
All you need to do is sum the votes by mapping true
values to 1
and false
values to -1
.
_ItemsService.GetAll(x => x.ItemVotes)
.Sum(v => v.Vote ? 1 : -1)
Upvotes: 1