zoukankan      html  css  js  c++  java
  • mongodb 踩坑记录

    Map-Reduce

    Map-Reduce 是 mongodb 处理批量数据的大杀器,凡是数据量大并且定时处理能满足需求的,都可以试着扔给 mongodb,让它去 Map-Reduce。

    以下截取自文档的图,可以清楚的说明 Map-Reduce 的执行过程。先看图:

    MapReduce

    回答问题,Map-Reduce 的执行过程是先 map 然后 reduce 么?

    是?恭喜入坑!而且是自己挖坑自己填。仔细再看一遍上文的图,看到那个灰色的箭头了?不是每次 map 都有 reduce 的!

    如果 map 的结果不是数组,mongodb 就不会执行 reduce。很合理的处理逻辑。

    然后,只有入过坑才能意识到自己挖的坑:对于 map 到的数据,如果在 reduce 时希望做统一的处理,一定会发现数据结果是不完整的。

    mgo 时间

    mgo 是 golang 的 mongodb driver。

    首先,构建测试程序。

    package main
    
    import (
      "log"
      "time"
    
      "gopkg.in/mgo.v2"
      . "gopkg.in/mgo.v2/bson"
    )
    
    type TestTime struct {
      Id           ObjectId "_id"
      CreationTime time.Time
    }
    
    func main() {
      session, err := mgo.Dial("127.0.0.1")
      if err != nil {
        log.Fatalln("Fatal error:", err.Error())
      }
    
      defer session.LogoutAll()
      defer session.Close()
    
      tc := session.DB("test").C("testtime")
    
      t := time.Now()
      id := NewObjectId()
    
      test := TestTime{
        Id:           id,
        CreationTime: t,
      }
    
      tc.Insert(test)
    
      var testTime TestTime
      tc.FindId(id).One(&testTime)
    
      log.Println(t)
    
      log.Println(t == testTime.CreationTime)
    }
    

    UTC

    执行测试程序,查看 mongodb 数据

    /* 0 */
    {
        "_id" : ObjectId("548d0b3194e33700f5ffaba9"),
        "creationtime" : ISODate("2014-12-14T03:59:45.123Z")
    }
    

    时间已经是 UTC 了,没有必要 time.Now().UTC(),当然,执行下 .UTC() 代码看起来更明确,也耗费不了多少 CPU,因为,.UTC() 仅仅是赋值时间的 location,其源码如下:

    func (t Time) UTC() Time{
      t.loc = UTC
      return t
    }
    

    精度

    mgo 直接以 time.Time 类型插入 mongodb 的时间精度与 time.Now() 的时间精度是不同的:

    • mgo 精度为 ms
    • time.Now() 精度为 ns2014-12-14 11:59:45.123670247 +0800 CST

    所以,上文 log.Println(t == testTime.CreationTime) 打印结果是 false

    _id 索引

    _id 是 mongodb 每个文档必备字段,而且是默认索引,就是说不管你用不用,它都会建立索引并占用存储空间。

    在设计存储结构时,只要能保证唯一性,即可将其作为 _id,例如:

    {
        "_id" : {
            "nickname" : "busyStone",
            "index" : 1
        },
        "creationtime" : ISODate("2014-11-09T02:00:44.496Z")
    }
    

    mongodb 是支持组合索引的,那么,_id.nickname 是不是也可以作为索引用呢?

    在选中的 collection 上执行 .find({"id.nickname":"busyStone"}).explain()nscanned 字段并不是预想中的 1,因为,建立的索引是这样的:

    {
        "_id" : 1
    }
    

    所以,老老实实自己个建索引吧。

  • 相关阅读:
    NFS
    Linux ISO镜像挂载
    Python3.6 提示 ModuleNotFoundError: No module named '_ssl' 模块问题
    mysql 5.7 ERROR 1054(42S22) Unknown column 'password' in ‘field list’ 报错
    Redis + keepalived 高可用行配置检测脚本
    Linux 文件大小查找排序
    查看 Centos 7 的MAC 地址
    Discuz 论坛 (LAMP环境)
    SVN
    systemctl
  • 原文地址:https://www.cnblogs.com/shanpow/p/4169773.html
Copyright © 2011-2022 走看看