RavenDB复杂索引

时间:2013-02-27 23:58:23

标签: map indexing group-by ravendb reduce

虽然我对将RavenDB用作OLTP应用程序存储的想法感到非常兴奋,但我对Linq / Map-Reduce索引实现有点麻烦。

这是我正在尝试做的事情 - 我有文件 -

Event {
   UserId:  "1",
   Location : "X",
   EventDate : "1/1/2010",
   EventType : "type A"
}
...
Event {
   UserId:  "2",
   Location : "Y",
   EventDate : "1/1/2011",
   EventType : "type B"
}

应该执行的操作查询/索引是

“在按位置,事件分组的特定日期范围内为特定用户带来不同的事件”

结果示例:

Location | Count(EventA) | Count(EventB) 
---------------------------------------
X        | 10            |     2
Y        |  4            |    22

我相信这应该是直截了当的。我可能只是错过了一些东西。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您所询问的是报告的典型案例。这是RavenDB不适合(http://ravendb.net/docs/server/bundles/index-replication)的一件事。您的问题类似于SQL Server Analysis Services中多维数据集的结构。

enter image description here

这种情况下的问题是日期范围。如果范围是固定的,比如我想知道它每个月,你可以在一个索引中做到这一点,但如果范围是临时的,那么我相信这在Raven中不可能通过使用索引而且可能不是偶数一个查询,因为您必须进行分组客户端,因此必须检索大量文档(远远超过Raven的默认值128)。

但是如果有人在我们省略日期范围的索引中通过示例搜索多个组,那么在跟踪索引实现,其中结果按用户ID分组,位置和事件类型可以是一个解决方案:

public class Index : AbstractIndexCreationTask<Index.Result>
{
    public class Result
    {
        public string UserId { get; set; }
        public string Location { get; set; }
        public string EventType { get; set; }
        public int Count { get; set; }
    }

    public Index()
    {
        Map = events => from e in events
                        select new Result
                        {
                            UserId = e.UserId,
                            Location = e.Location,
                            EventType = e.EventType,
                            Count = 1
                        };

        Reduce = results => from result in results
                            group result by new { result.UserId, result.Location, result.EventType }
                                into g
                                select new Result
                                {
                                    UserId = g.Key.UserId,
                                    Location = g.Key.Location,
                                    EventType = g.Key.EventType,
                                    Count = g.Sum(x => x.Count)
                                };
    }
}

这会给你这个结果

UserId   | Location | EventType     | Count
-------------------------------------------
1        | X        | A             |     2
1        | X        | B             |     4
1        | Y        | A             |    22
1        | Y        | B             |     6
2        | X        | A             |     7
2        | X        | B             |     3
2        | Y        | A             |     9
2        | Y        | B             |    16

然后,您可以查询该索引并对查询结果进行其他分组。