5

我是 RavenDB 的新手,到目前为止我很喜欢它。我还有一个要为我的项目创建的索引。

问题

我有数以千计的调查回复(即“ Submissions”),每个提交都有一系列特定问题的答案(即“ Answers”),每个答案都有一系列选择的选项(即“ Values”)。

单曲Submission基本上是这样的:

{
  "SurveyId": 1,
  "LocationId": 1,
  "Answers": [
    {
      "QuestionId": 1,
      "Values": [2,8,32],
      "Comment": null
    },
    {
      "QuestionId": 2,
      "Values": [4],
      "Comment": "Lorem ipsum"
    },
    ...more answers...
  ]
}

更多问题:我必须能够按 SurveyId、LocationId、QuestionId、创建日期进行过滤。据我了解,这是在查询时完成的......我只需要确保这些属性存在于转换结果中(或者它是减少结果?或两者兼而有之?)。如果我是对的,那么这不是一个问题。

所需的结果

每个调查的每个问题都需要一个对象,该对象给出每个选项的总和。希望它是不言自明的:

[
    {
        SurveyId: 1,
        QuestionId: 1,
        NumResponses: 976,
        NumComments: 273,
        Values: {
            "1": 452, // option 1 selected 452 times
            "2": 392, // option 2 selected 392 times
            "4": 785  // option 4 selected 785 times
        }
    },
    {
        SurveyId: 1,
        QuestionId: 2,
        NumResponses: 921,
        NumComments: 46,
        Values: {
            "1": 325,
            "2": 843,
            "4": 119,
            "8": 346,
            "32": 524
        }
    },
    ...
]

我的尝试

我没有走得太远,我认为这篇文章正在引导我走上正确的道路,但它对我的价值观列表没有帮助。我已经搜索和搜索,但找不到任何方向来处理这样的嵌套数组。这是我到目前为止:

地图:

from submission in docs.Submissions
from answer in submission.Answers
where answer.WasSkipped != true && answer.Value != null
select new {
    SubmissionDate = submission["@metadata"]["Last-Modified"],
    SurveyId = submission.SurveyId,
    LocationId = submission.LocationId,
    QuestionId = answer.QuestionId,
    Value = answer.Value
}

减少:

??

转换:

from result in results
from answer in result.Answers
where answer.WasSkipped != true && answer.Value != null
select new {
    SubmissionDate = result["@metadata"]["Last-Modified"],
    SurveyId = result.SurveyId,
    LocationId = result.LocationId,
    QuestionId = answer.QuestionId,
    Value = answer.Value
}

值得一提的是,它托管在 RavenHQ 上。

太久了,我一直在做这件事,但不能把它做好。非常感谢任何帮助我获得所需结果的帮助!

4

1 回答 1

7

假设您的 C# 类如下所示:

public class Submission
{
    public int SurveyId { get; set; }
    public int LocationId { get; set; }
    public IList<Answer> Answers { get; set; }
}

public class Answer
{
    public int QuestionId { get; set; }
    public int[] Values { get; set; }
    public string Comment { get; set; }
}

如果您正在运行 RavenDB 2.5.2637 或更高版本,您现在可以使用字典结果类型:

public class Result
{
    public int SurveyId { get; set; }
    public int QuestionId { get; set; }
    public int NumResponses { get; set; }
    public int NumComments { get; set; }
    public Dictionary<int, int> Values { get; set; }
}

如果您正在运行任何早期版本(包括 2.0 版本),那么您将无法使用字典,但您可以使用 anIList<KeyValuePair<int,int>>来代替。

这是索引:

public class TestIndex : AbstractIndexCreationTask<Submission, Result>
{
    public TestIndex()
    {
        Map = submissions =>
              from submission in submissions
              from answer in submission.Answers
              select new
              {
                  submission.SurveyId,
                  answer.QuestionId,
                  NumResponses = 1,
                  NumComments = answer.Comment == null ? 0 : 1,
                  Values = answer.Values.ToDictionary(x => x, x => 1)
                  //Values = answer.Values.Select(x => new KeyValuePair<int, int>(x, 1))
              };

        Reduce = results =>
                 from result in results
                 group result by new { result.SurveyId, result.QuestionId }
                 into g
                 select new
                 {
                     g.Key.SurveyId,
                     g.Key.QuestionId,
                     NumResponses = g.Sum(x => x.NumResponses),
                     NumComments = g.Sum(x => x.NumComments),
                     Values = g.SelectMany(x => x.Values)
                               .GroupBy(x => x.Key)
                               .ToDictionary(x => x.Key, x => x.Sum(y => y.Value))
                               //.Select(x => new KeyValuePair<int, int>(x.Key, x.Sum(y => y.Value)))
                 };
    }
}

(不需要转换步骤。)

如果您不能使用 2.5.2637 或更高版本,则将这些.ToDictionary行替换为它们正下方的注释行,并IList<KeyValuePair<int,int>>在结果类中使用 an。

允许在 map/reduce 中使用字典的修复是基于您的帖子帮助识别的这个问题。谢谢!

于 2013-07-06T03:31:33.677 回答