【问题标题】:Raven DB: How to create "UniqueVisitorCount by date" indexRavendb:如何创建“按日期计算的唯一访客数”索引
【发布时间】:2012-05-15 09:00:06
【问题描述】:

我有一个应用程序来跟踪网站的页面访问。 这是我的模型:

public class VisitSession {
    public string SessionId { get; set; }
    public DateTime StartTime { get; set; }
    public string UniqueVisitorId { get; set; }
    public IList<PageVisit> PageVisits { get; set; }
}

当访问者访问网站时,访问会话开始。一次访问会话有许多页面访问。当访问者第一次访问网站时,跟踪器将写入一个 UniqueVisitorId (GUID) cookie。这样我们就可以知道访客是否是回访者。

现在,我想知道有多少唯一身份访问者在某个日期范围内访问了该网站。也就是说,我想在我们的网页中显示这样的表格;

Date        | Unique Visitors Count
------------+-----------------------
2012-05-01  | 100
2012-05-02  | 1000
2012-05-03  | 120

我想在 RavenDB 中创建一个索引来执行此操作。但我不知道如何编写 Map/Reduce 查询。我虽然可以是这样的:

public class UniqueVisitor_ByDate : AbstractIndexCreationTask<VisitSession, UniqueVisitorByDate>
{
    public UniqueVisitor_ByDate()
    {
        Map = sessions => from s in sessions
                            select new
                            {
                                s.StartTime.Date,
                                s.UniqueVisitorId
                            };

        Reduce = results => from result in results
                            group result by result.Date into g
                            select new
                            {
                                Date = g.Key,
                                UniqueVisitorCount = g.Distinct()
                            };
    }
}

但它不起作用。在 Ayende 的电子书中,我知道 Map 函数的结果应该与 Reduce 函数的结果相同。那么如何编写正确的 map/reduce 函数呢?

【问题讨论】:

    标签: c# mapreduce ravendb


    【解决方案1】:

    这个索引应该做你想做的:

    public class UniqueVisitor_ByDate : AbstractIndexCreationTask<VisitSession, UniqueVisitorByDate>
    {
        public UniqueVisitor_ByDate()
        {
            Map = sessions => 
                from s in sessions
                select new {
                    s.StartTime.Date,
                    s.UniqueVisitorId,
                    Count = 1,
                };
    
            Reduce = results =>
                from result in results
                group result by result.Date
                into g
                select new UniqueVisitorByDate {
                    Date = g.Key,
                    Count = g.Select(x => x.UniqueVisitorId).Distinct().Count(),
                    UniqueVisitorId = g.FirstOrDefault().UniqueVisitorId,
                };
        }
    }
    

    请注意,它需要“reduce”中的额外“UniqueVisitorId”属性和地图中的“count”属性,但您可以忽略这些。

    【讨论】:

    • 但是在 UniqueVisitorByDate 类中添加“UniqueVisitorId”看起来很奇怪,有没有更好的解决方案?
    • 我不知道。您可以将属性名称更改为“TempId_DO_NOT_USE”之类的名称,以表明它不应在您的应用程序中使用。
    • @DylanLin UniqueVisitorId 必须是 UniqueVisitorByDate 的一部分,因为 Map 和 Reduce 必须生成相同形状的对象。
    • 但仍然使 UniqueVisitorByDate 类不优雅:(
    • 优雅或实用主义...在这种情况下,因为该类仅用于显示结果,而不是您的域或业务逻辑的一部分,我认为为索引付出的代价很小这确实有效! :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 2012-02-09
    • 2021-08-30
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多