【问题标题】:MongoDB Approaches for storing large amounts of metrics / analytics dataMongoDB 存储大量指标/分析数据的方法
【发布时间】:2017-03-29 20:24:43
【问题描述】:

我们计划使用 MongoDB 来存储大量的分析数据,例如视图和点击。我不确定在 MongoDB 中构建文档以帮助查询和减小数据库大小的最佳方式。

我们需要根据页面名称、客户端和操作类型来记录操作。理想情况下,我们需要下降到年/月/日/小时级别的统计数据,我们不需要或关心每秒或每分钟的视图。虽然这个文档结构看起来不错,但我知道 100 个访问者会生成 100 个新文档。

{ 
  "_id" : ObjectId( "4dabdef81a34961506040000" ),
  "pagename" : "Hello",
  "action" : "view",
  "client" : "client-name",
  "time" : Date( "Mon Apr 18 07:49:28 2011" )
}

是否有最佳实践方法,使用$inc 或Capped Collections?

【问题讨论】:

    标签: database-design mongodb statistics analytics


    【解决方案1】:

    更新答案

    在 mongo shell 中一起破解:

    use pagestats;
    
    // a little helper function
    var pagePerHour = function(pagename) {
        d = new Date();
        return {
            page : pagename,
            year: d.getUTCFullYear(),
            month: d.getUTCMonth(),
            day : d.getUTCDate(),
            hour: d.getUTCHours(),
        }
    }
    
    // a pageview happened
    db.pagestats.update(
        pagePerHour('Hello'),
        { $inc : { views : 1 }},
        true ); //we want to upsert
    
    // somebody tweeted our page twice!
    db.pagestats.update(
        pagePerHour('Hello'),
        { $inc : { tweets : 2 }},
        true ); //we want to upsert
    
    db.pagestats.find();
    // { "_id" : ObjectId("4dafe88a02662f38b4a20193"),
    //   "year" : 2011, "day" : 21, "hour" : 8, "month" : 3,
    //   "page" : "Hello",
    //   "tweets" : 2, "views" : 1 }
    
    // 24 hour summary 'Hello' on 2011-4-21
    for(i = 0; i < 24; i++) {
        //careful: days (1-31), month (0-11) and hours (0-23)
        stats = db.pagestats.findOne({ page: 'Hello', year: 2011, month: 3, day : 21, hour : i})
        if(stats) {
            print(i + ': ' + stats.views + ' views')
        } else {
            print(i + ': no hits')
        };
    }
    

    根据您要跟踪的方面,您可能会考虑添加更多集合(例如,用于以用户为中心的跟踪的集合)。希望对您有所帮助。

    另请参阅

    Blogpost about Analytics Data

    【讨论】:

    • 有趣,如果我想显示过去一天中每个小时的“Hello”的观看次数,find() 语法会是什么样子?
    • .. 那么这个解决方案不会完全理想。但请稍等,我会发布更新。
    • 在我闭嘴之前的最后一件事:MongoDB 将为您提供尝试不同方法的速度和灵活性。不要想太多,砍掉,看看它是否符合你的需求,如果不符合就改变它:)
    • 查询复合索引时要非常小心(此处需要):“如果查询中存在索引的第一个键,则查询优化器可能会选择该索引。如果查询中不存在第一个键,只有在明确提示时才会使用索引。虽然在查询中存在索引字段的任意子集的许多情况下可以使用索引,但作为一般规则,给定的最佳索引查询是查询字段在任何非查询字段之前的那些。” mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeysIndexes
    【解决方案2】:

    我不会太担心空间,Mongo 在这方面可以无限​​扩展,增加更多空间会相当便宜。

    需要注意的一点是,如果您不断更新文档,它的大小将会增长,这意味着 Mongo 最终需要在索引中为它找到一个新位置。如果您有很多文档要更新并且大小增加,Mongo 将需要大量复制这些文档,这可能会显着减慢速度。当然,这一切都取决于您期望的流量。

    根据我的经验,请使用不需要更新文档的简单文档格式,这可能会使您以后的查询变得复杂,但您可以使用 map/reduce 来获取所需的任何信息,而不管您的文档如何结构(如果有足够的经验可以做任何事情,map reduce 非常灵活)。

    【讨论】:

      猜你喜欢
      • 2013-11-14
      • 2011-01-21
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多