C# 嵌套LINQ表达式的RavenDB解决方案
我在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
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();