如何正确组织 RavenDB Map/Reduce 结果?
How do I organize RavenDB Map/Reduce results properly?
我有以下 RavenDB 索引。
public class MyDomain_WeeklyPerYear : AbstractIndexCreationTask<Entities.MyDomain, MyDomain_YearlyTotals.Result>
{
public class Result
{
public int ProcessWeek { get; set; }
public int ProcessYear { get; set; }
public int Total { get; set; }
public object Weeks { get; set; }
public string Workspace { get; set; }
}
public MyDomain_WeeklyPerYear()
{
Map = data => data
.Select(x => new
{
x.ProcessWeek,
x.ProcessYear,
x.Workspace,
Total = 1,
Weeks = (List<object>) null
});
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.OrderBy(x => x.Key)
.Select(x => new
{
ProcessWeek = 0,
ProcessYear = x.Key,
Workspace = (string) null,
Total = 0,
Weeks = x
.GroupBy(y => y.ProcessWeek)
.OrderBy(y => y.Key)
.Select(y => new
{
Week = y.Key,
Total = y.Sum(z => z.Total)
})
.ToList()
});
}
}
当我 运行 使用以下查询时,我得到以下结果。
var data = await Session
.Query<MyDomain_WeeklyPerYear.Result, MyDomain_WeeklyPerYear>()
.ToListAsync();
[
{
"processWeek": 0,
"processYear": 2012,
"total": 0,
"weeks": [
{
"Week": 1,
"Total": 8
},
{
"Week": 49,
"Total": 4
},
{
"Week": 50,
"Total": 6
},
{
"Week": 51,
"Total": 11
},
{
"Week": 52,
"Total": 4
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2013,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2014,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2015,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2016,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2017,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2018,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2019,
"total": 0,
"weeks": [
{
"Week": 2,
"Total": 14
},
{
"Week": 3,
"Total": 30
},
{
"Week": 4,
"Total": 42
},
{
"Week": 5,
"Total": 52
},
{
"Week": 6,
"Total": 51
},
{
"Week": 7,
"Total": 39
},
{
"Week": 8,
"Total": 53
},
{
"Week": 9,
"Total": 47
},
{
"Week": 10,
"Total": 52
}
],
"workspace": null
}
]
数据结构是我想要的正确JSON结构,但似乎遗漏了很多数据。我在 2012 年和 2019 年获得结果(正确)。但是其他年份是空的,尽管我 100% 确定它们包含的数据比 2012 年和 2019 年多得多。
当我将 reduce 更改为以下内容时(删除了第二个 .Select()
):
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.OrderBy(x => x.Key)
.Select(x => new
{
ProcessWeek = 0,
ProcessYear = x.Key,
Workspace = (string) null,
Total = 0,
Weeks = x
.GroupBy(y => y.ProcessWeek)
.OrderBy(y => y.Key)
.ToList()
});
结果给出了这样一个奇怪的结构(2013年的小抓包见下图,因为完整的JSON很长)。
[
{
... other years
},
{
"processWeek": 0,
"processYear": 2013,
"total": 0,
"weeks": [
{
"ProcessWeek": 0,
"ProcessYear": 2013,
"Workspace": null,
"Total": 0,
"Weeks": [
[
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
}
],
[
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
]
]
}
]
},
{
... other years
}
]
如您所见,2013 年有数据,尽管在第一个 JSON 结果中它没有显示,但它有一个我没想到的奇怪结构。我想这可能就是为什么它没有在第一次 reduce 中显示 2013 年数据的原因。
我的问题:
- 为什么它在第一次 reduce 时给我提供了正确的结构和一些正确的数据(在 2012 年和 2019 年),但缺少其他年份?
- 为什么它给了我奇怪的 JSON 结构,在第二个 reduce 中,显示其他年份有数据?
- 如何从第一个 JSON 示例中获取结构中的所有数据?
我已经在这个问题上停留了很长一段时间,如果能提供一些帮助,我们将不胜感激。
RavenDB Client: 4.1.4
RavenDB Server: 4.1.3
问题是您在 reduce 中创建假数据,但多次调用 reduce。你必须能够递归地处理它。
尝试这样的事情:
public MyDomain_WeeklyPerYear()
{
Map = data => data
.Select(x => new
{
x.ProcessYear,
Weeks = new [] {
new {Week = x.ProcessWeek, Total = 1}
}
});
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.Select(x => new
{
ProcessYear = x.Key,
Weeks = x.SelectMany(y=>y.Weeks)
.GroupBy(y => y.ProcessWeek)
.Select(y => new
{
Week = y.Key,
Total = y.Sum(z => z.Total)
})
});
}
我有以下 RavenDB 索引。
public class MyDomain_WeeklyPerYear : AbstractIndexCreationTask<Entities.MyDomain, MyDomain_YearlyTotals.Result>
{
public class Result
{
public int ProcessWeek { get; set; }
public int ProcessYear { get; set; }
public int Total { get; set; }
public object Weeks { get; set; }
public string Workspace { get; set; }
}
public MyDomain_WeeklyPerYear()
{
Map = data => data
.Select(x => new
{
x.ProcessWeek,
x.ProcessYear,
x.Workspace,
Total = 1,
Weeks = (List<object>) null
});
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.OrderBy(x => x.Key)
.Select(x => new
{
ProcessWeek = 0,
ProcessYear = x.Key,
Workspace = (string) null,
Total = 0,
Weeks = x
.GroupBy(y => y.ProcessWeek)
.OrderBy(y => y.Key)
.Select(y => new
{
Week = y.Key,
Total = y.Sum(z => z.Total)
})
.ToList()
});
}
}
当我 运行 使用以下查询时,我得到以下结果。
var data = await Session
.Query<MyDomain_WeeklyPerYear.Result, MyDomain_WeeklyPerYear>()
.ToListAsync();
[
{
"processWeek": 0,
"processYear": 2012,
"total": 0,
"weeks": [
{
"Week": 1,
"Total": 8
},
{
"Week": 49,
"Total": 4
},
{
"Week": 50,
"Total": 6
},
{
"Week": 51,
"Total": 11
},
{
"Week": 52,
"Total": 4
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2013,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2014,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2015,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2016,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2017,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2018,
"total": 0,
"weeks": [
{
"Week": 0,
"Total": 0
}
],
"workspace": null
},
{
"processWeek": 0,
"processYear": 2019,
"total": 0,
"weeks": [
{
"Week": 2,
"Total": 14
},
{
"Week": 3,
"Total": 30
},
{
"Week": 4,
"Total": 42
},
{
"Week": 5,
"Total": 52
},
{
"Week": 6,
"Total": 51
},
{
"Week": 7,
"Total": 39
},
{
"Week": 8,
"Total": 53
},
{
"Week": 9,
"Total": 47
},
{
"Week": 10,
"Total": 52
}
],
"workspace": null
}
]
数据结构是我想要的正确JSON结构,但似乎遗漏了很多数据。我在 2012 年和 2019 年获得结果(正确)。但是其他年份是空的,尽管我 100% 确定它们包含的数据比 2012 年和 2019 年多得多。
当我将 reduce 更改为以下内容时(删除了第二个 .Select()
):
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.OrderBy(x => x.Key)
.Select(x => new
{
ProcessWeek = 0,
ProcessYear = x.Key,
Workspace = (string) null,
Total = 0,
Weeks = x
.GroupBy(y => y.ProcessWeek)
.OrderBy(y => y.Key)
.ToList()
});
结果给出了这样一个奇怪的结构(2013年的小抓包见下图,因为完整的JSON很长)。
[
{
... other years
},
{
"processWeek": 0,
"processYear": 2013,
"total": 0,
"weeks": [
{
"ProcessWeek": 0,
"ProcessYear": 2013,
"Workspace": null,
"Total": 0,
"Weeks": [
[
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 7,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
}
],
[
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
{
"ProcessWeek": 12,
"ProcessYear": 2013,
"Workspace": "my-workspace",
"Total": 1,
"Weeks": null
},
]
]
}
]
},
{
... other years
}
]
如您所见,2013 年有数据,尽管在第一个 JSON 结果中它没有显示,但它有一个我没想到的奇怪结构。我想这可能就是为什么它没有在第一次 reduce 中显示 2013 年数据的原因。
我的问题:
- 为什么它在第一次 reduce 时给我提供了正确的结构和一些正确的数据(在 2012 年和 2019 年),但缺少其他年份?
- 为什么它给了我奇怪的 JSON 结构,在第二个 reduce 中,显示其他年份有数据?
- 如何从第一个 JSON 示例中获取结构中的所有数据?
我已经在这个问题上停留了很长一段时间,如果能提供一些帮助,我们将不胜感激。
RavenDB Client: 4.1.4
RavenDB Server: 4.1.3
问题是您在 reduce 中创建假数据,但多次调用 reduce。你必须能够递归地处理它。 尝试这样的事情:
public MyDomain_WeeklyPerYear()
{
Map = data => data
.Select(x => new
{
x.ProcessYear,
Weeks = new [] {
new {Week = x.ProcessWeek, Total = 1}
}
});
Reduce = results => results
.GroupBy(x => x.ProcessYear)
.Select(x => new
{
ProcessYear = x.Key,
Weeks = x.SelectMany(y=>y.Weeks)
.GroupBy(y => y.ProcessWeek)
.Select(y => new
{
Week = y.Key,
Total = y.Sum(z => z.Total)
})
});
}