如何正确组织 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 年数据的原因。

我的问题:

  1. 为什么它在第一次 reduce 时给我提供了正确的结构和一些正确的数据(在 2012 年和 2019 年),但缺少其他年份?
  2. 为什么它给了我奇怪的 JSON 结构,在第二个 reduce 中,显示其他年份有数据?
  3. 如何从第一个 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)
                })
        });
}