I have simple set of objects stored in RavenDB:
public class Question
{
public string Id { get; set; }
public DateTime CreatedOn { get; set; }
public ICollection<User> Supporters { get; set; }
public ICollection<Answer> Answers { get; set; }
}
public class Answer
{
public string Id { get; set; }
public bool IsOfficial { get; set; }
}
Now I want to query RavenDB to give me set of questions, ordered firstly by number of supporters, next by condition – if a question has any official answer, and in the and, by question creation date. So I’ve written a query:
var questions = DocumentSession.Query<Question>().AsQueryable();
questions = questions
.OrderByDescending(x => x.Supporters.Count)
.ThenByDescending(x => x.Answers.Any(a => a.IsOfficial)) //EDIT: source of exception
.ThenByDescending(x => x.CreatedOn)
.Take(15);
var result = questions.ToList();
which throws an exception:
System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.MemberExpression'
The query is logically correct and works, when I use linq-to-objects, and simply add .ToList() to first line:
var questions = DocumentSession.Query<Question>().Tolist().AsQueryable();
// next lines stay unchanged
I don’t want to do it because of performance issues (this change forces all questions to be loaded from database into memory before filtering).
How to make this working without performance impact ? Maybe shell I define an index ? How it should looks like then ?
Based on Bear Alexander response, I’ve done this like that:
It works and I believe it is more efficient than my original version. If it can be done in any more elegant way, I’d appreciate any ideas. Regards.