Mongodb 多集合 多表 統計實戰

來源:互聯網
上載者:User
Mongodb 多集合 多表 統計實戰

完成以下報表:

涉及到的表person、appointmentRecord 人數統計

在person表使用彙總函式
db.Person.aggregate()就行

[  {    $match: {      'dateOfBirth': {        $gt: '1986-12-02',        $lt: '1996-12-02',      }    }  }, {    $group: {      _id: '$SEX',      count: {        $sum: 1      },    }  },]
統計常掛科室

科室和使用者通過userid關聯
如何管理兩個集合呢
- Person 有1058萬條資料 分區sharded = true
- AppointmentRecord 有300來萬資料 沒分區
邏輯很簡單
* 1.根據使用者篩選挂號記錄
* 2.在挂號記錄 中按照醫院、科室分組計算數量
* 3.選擇數量前10的分組 錯誤方案一 用彙總函式$lookup

db.AppointmentRecord.aggregate([  {//加limit是為了用小資料測試    $limit: 10000  },{    $lookup: {      from: "Person",      localField: "userid",      foreignField: "userid",      as: "ar_docs",    }  },  // {'arr':{'$elemMatch':{'addr':'ddr2','dept':'oo'}}}  {    $match: {      'ar_docs': {        '$elemMatch': {          'channelCode': 'WECHAT'        }      }    }, {      $group : {        _id: {          hospitalCode: '$hospitalCode',          hospitalName: '$hospitalName',          LOC: '$cTLOCDesc',        },        count: {          $sum: 1        },      }    }, {      $sort : {        count: -1      }    }, {      $limit : 10    },  ])

報錯 因為lookup不支援分區的集合。 錯誤方案二 用mapReduce

mapReduce不直接支援多個集合的操作除非你用dbref。
我們的表沒有dbref

那試試外面的變數它能接受不

var userArr2 = [];db.PAPerson.find({'iDCard':{$ne:null},$where: function() {     var birth = this.iDCard.substr(6,8);    if (birth > 19861202 && birth < 19961202) {        return true;    } }},{    uRHospitalID:1,     userid:1,    _id:0}).limit(5000).forEach((it)=> {     userArr2.push(it.userid +'-' + it.uRHospitalID);});print(userArr2.length)var mapfun = function(){          if (userArr2.indexOf(this.userid +'-' + this.uRHospitalID) !== -1) {            emit(this.hospitalName + "-" + this.cTLOCDesc,1);          }       };db.AppointmentRecord.mapReduce(      mapfun, //mapFunction      function(key, values){          return Array.sum(values);      },//reduceFunction      {          limit: 10000,          query:{ 'channelCode': 'WECHAT' },          out: "output_user2_loc"      })

結果還是失敗 map方法不能接收到外面的變數,在裡面寫查詢的話db這關鍵字都找不到。 錯誤方案三 建立新表用彙總

lookup不支援分區的 那麼我就建立一個篩選person表插入一個新的集合好了:

db.Person.find({'iDCard':{$ne:null},$where: function() {    var birth = this.iDCard.substr(6,8);    if (birth > 19661202 && birth < 19761202) {        return true;    }}},{    uRHospitalID:1,    userid:1}).limit(10).batchSize(80000).forEach(function(it) {      db.xtemp_user4.insert(it);//40歲+就是user4});

新集合很快建立好了
那麼來彙總吧。

 db.AppointmentRecord.aggregate([    {$limit: 10000},    {      $match: {        'channelCode': 'WECHAT',      }    },    {        $lookup: {          from: "xtemp_user4",          localField: "userid",          foreignField: "userid",          as: "ar_docs",        }    },    {      $match: {        'ar_docs': {$elemMatch:{'userid':{$ne:null}}},      }    },    {      $group: {        _id: {          hospitalCode: '$hospitalCode',          hospitalName: '$hospitalName',          LOC: '$cTLOCDesc',        },        count: {          $sum: 1        },      }    }, {      $sort: {        count: -1      }    },     {      $limit: 10    },  ])

小資料測試也通過了 。
然而執行了一晚上也沒出結果。 方案四

用in

var parr4 = db.xtemp_user4.distinct("userid");db.AppointmentRecord.aggregate([    //{$limit: 1000},    {      $match:      {'channelCode':'WECHAT','userid':{$in: parr4}}    },    {      $group: {        _id: {        LOC: '$cTLOCDesc',          hospitalCode: '$hospitalCode',          hospitalName: '$hospitalName',        },        count: {          $sum: 1        },      }    }, {      $sort: {        count: -1      }    },    {      $limit: 10    },  ])

只用了50s左右結果就出來了。。
因為mongodb接觸得不多搞了幾天才搞好。查了很多部落格很多官網資料,mongodb版本有些函數不支援的坑就不說了。看見例子不是很多就寫了這篇部落格希望大家少踩坑。
有更好的方案歡迎反饋。

對了,以上代碼運行在mongodb 3.2.9。

加batchSize是因為不加會報cursor逾時。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.