C# 嵌套LINQ表达式的RavenDB解决方案

C# 嵌套LINQ表达式的RavenDB解决方案,c#,linq,ravendb,C#,Linq,Ravendb,我在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; } } pub

我在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; }
}
当我使用linq to objects并简单地将.ToList()添加到第一行时,查询在逻辑上是正确的,并且可以工作:

var questions = DocumentSession.Query<Question>().Tolist().AsQueryable();
// next lines stay unchanged
var questions=DocumentSession.Query().Tolist().AsQueryable();
//下一行保持不变
由于性能问题,我不想这样做(这一更改强制在筛选之前将所有问题从数据库加载到内存中)


如何使其在不影响性能的情况下工作?也许我可以定义一个索引?它应该是什么样子?

Raven无法支持LINQ查询中的计算,因此这应该可以工作(问题子句已删除):


用于您的目的的自定义索引基本上是对类的重新创建,其中包含额外的字段(以及一些支持它的逻辑)。似乎您不想在当前类中添加更多字段,是否可以在项目中添加更多类

下面是一个例子:

public class Question_WithAnyOfficial: AbstractIndexCreationTask<Question>
{
    public class Question_WithAnyOfficial()
    {
        Map = questions => from question in questions
                           // New Anonymous Type
                           select new
                           {
                                Id = question.Id,
                                CreatedOn = question.CreatedOn,
                                Supporters = question.Supporters,
                                Answers = question.Answers,
                                AnyOfficial = question.Answers.Where(a => a.IsOfficial).Any()
                           };
    }
}
公共类问题\u与任何官员:AbstractIndexCreationTask
{
公共课问题与任何官员()
{
映射=问题=>来自问题中的问题
//新匿名类型
选择新的
{
Id=question.Id,
CreatedOn=question.CreatedOn,
支持者=问题。支持者,
答案=问题。答案,
AnyOfficial=question.Answers.Where(a=>a.IsOfficial).Any()
};
}
}
然后您可以查询:

var questions = DocumentSession.Query<Question_WithAnyOfficial>()
                .OrderByDescending(x => x.Supporters.Count)
                .ThenByDescending(x => x.AnyOfficial)
                .ThenByDescending(x => x.CreatedOn)
                .Take(15)
                .ToList();         
var questions=DocumentSession.Query()
.OrderByDescending(x=>x.supports.Count)
.然后按降序(x=>x.AnyOfficial)
.然后按降序(x=>x.CreatedOn)
.Take(15)
.ToList();

别忘了,当你的应用程序启动时,你必须注册索引。

根据Bear Alexander的回复,我这样做了:

public class QuestionByAnyOfficial : AbstractIndexCreationTask<Question, QuestionByAnyOfficial.Result>
{
    public class Result
    {
        public string Id;
        public bool AnyOfficial;
        public int SupportersCount;
        public DateTime CreatedOn;
    }

    public QuestionByAnyOfficial()
    {
        Map = questions => from question in questions                               
                           select new
                              {
                                  Id = question.Id,                                              
                                  AnyOfficial = question.Answers.Any(a => a.IsOfficial),
                                  SupportersCount = question.Supporters.Count,
                                  CreatedOn = question.CreatedOn
                              };            
    }
}

var questionIds = DocumentSession.Query<QuestionByAnyOfficial.Result, QuestionByAnyOfficial>()
                       .OrderByDescending(x => x.SupportersCount)
                       .ThenByDescending(x => x.AnyOfficial)
                       .ThenByDescending(x => x.CreatedOn)
                       .Take(NumberOfQuestions)
                       .Select(x => x.Id);
var questions = DocumentSession.Load<Question>(questionIds);
var result = questions.ToList();
任何人发布的公共类问题官员:AbstractIndexCreationTask { 公开课成绩 { 公共字符串Id; 公职人员; 公众支持人数; 公共日期时间; } 任何官员的公开问题 { 映射=问题=>来自问题中的问题 选择新的 { Id=question.Id, AnyOfficial=问题。答案。Any(a=>a.IsOfficial), 支持者人数=question.supports.Count, CreatedOn=question.CreatedOn }; } } var questionId=DocumentSession.Query() .OrderByDescending(x=>x.SupportersCount) .然后按降序(x=>x.AnyOfficial) .然后按降序(x=>x.CreatedOn) .回答(问题数量) .选择(x=>x.Id); var questions=DocumentSession.Load(问题ID); var result=questions.ToList();
它是有效的,我相信它比我原来的版本更有效。如果能用更优雅的方式来做,我会很感激你的建议。问候。

您是否尝试过不使用
ToList()
.AsQueryable()
的查询,就像:
var questions=DocumentSession.query().OrderByDescending()一样在哪一行引发异常?当调用ToList()时,或当您尝试访问支持者计数时,或调用Any()时,或在其他地方时,是否会发生这种情况?我同意MGA的观点,即不需要.AsQueryable()。我还认为为计数和Any()建立索引是个好主意。@Bear Alexander:我已经编辑了这个问题并指出了错误的来源。实际上不需要AsQueryable()。索引线索似乎很有趣。你能根据我的情况发布这样的索引示例,以及保留我的逻辑并返回所需结果的修改后的查询吗?你好,再次感谢。我知道哪一行是问题的根源。我只是想知道我必须做什么样的改变才能保持这种逻辑。这个额外的字段看起来还可以,但是还有其他选项吗?一些自定义索引呢?Jarek,是的-如果您不想在文档中包含“AreaAllanswersOfficial”属性,您当然可以使用一个简单的地图索引来进行计算。其实很简单,你们应该有问题。谢谢你们的努力。根据你的回答,我创建了索引。你的代码对我不起作用,但给了我一个线索。事实上,我可以在我的项目中增加更多的课程。由于某些原因,我不想向我的域对象添加冗余字段,同样地,我的数据也不规范化。
var questions = DocumentSession.Query<Question>()
                .OrderByDescending(x => x.Supporters.Count)
                .ThenByDescending(x => x.AreAllAnswersOfficial)
                .ThenByDescending(x => x.CreatedOn)
                .Take(15);                
var result = questions.ToList();
public class Question_WithAnyOfficial: AbstractIndexCreationTask<Question>
{
    public class Question_WithAnyOfficial()
    {
        Map = questions => from question in questions
                           // New Anonymous Type
                           select new
                           {
                                Id = question.Id,
                                CreatedOn = question.CreatedOn,
                                Supporters = question.Supporters,
                                Answers = question.Answers,
                                AnyOfficial = question.Answers.Where(a => a.IsOfficial).Any()
                           };
    }
}
var questions = DocumentSession.Query<Question_WithAnyOfficial>()
                .OrderByDescending(x => x.Supporters.Count)
                .ThenByDescending(x => x.AnyOfficial)
                .ThenByDescending(x => x.CreatedOn)
                .Take(15)
                .ToList();         
public class QuestionByAnyOfficial : AbstractIndexCreationTask<Question, QuestionByAnyOfficial.Result>
{
    public class Result
    {
        public string Id;
        public bool AnyOfficial;
        public int SupportersCount;
        public DateTime CreatedOn;
    }

    public QuestionByAnyOfficial()
    {
        Map = questions => from question in questions                               
                           select new
                              {
                                  Id = question.Id,                                              
                                  AnyOfficial = question.Answers.Any(a => a.IsOfficial),
                                  SupportersCount = question.Supporters.Count,
                                  CreatedOn = question.CreatedOn
                              };            
    }
}

var questionIds = DocumentSession.Query<QuestionByAnyOfficial.Result, QuestionByAnyOfficial>()
                       .OrderByDescending(x => x.SupportersCount)
                       .ThenByDescending(x => x.AnyOfficial)
                       .ThenByDescending(x => x.CreatedOn)
                       .Take(NumberOfQuestions)
                       .Select(x => x.Id);
var questions = DocumentSession.Load<Question>(questionIds);
var result = questions.ToList();