前回はstatusをカウントするだけの単純な物
実際は、もっと複雑
けどいきなり複雑にしすぎてもついていけない。
そんな私に!!
日別で、アクセスユーザの何割が、特定の条件を満たしたかをとる処理を
かる〜く書いてみました。
特定の条件って、またむずかしいんじゃね?
その条件は
http status の 200と300を発生させ、尚且つ500は発生させていないユーザである事。
コレを今回の解析内容としてみます。
お題を考えるのがめんどかった(自分用なので)で、一旦これで
要は
ユーザ1が1日に発生させたstatusが200と300だけであれば合格
ユーザ2が1日に発生させたstatusが200と300と500であれば不合格
とりあえず、データの準備
db.access.save({user_id:'A001',status:200,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A001',status:300,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A002',status:200,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A002',status:300,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A002',status:500,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A003',status:200,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A003',status:300,create_dt:ISODate("2013-06-10T15:00:00Z")});
db.access.save({user_id:'A001',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A002',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A003',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A004',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A004',status:300,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A005',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A005',status:300,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A006',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A006',status:300,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A007',status:200,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A007',status:300,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A007',status:500,create_dt:ISODate("2013-06-11T15:00:00Z")});
db.access.save({user_id:'A001',status:200,create_dt:ISODate("2013-06-12T15:00:00Z")});
db.access.save({user_id:'A002',status:200,create_dt:ISODate("2013-06-12T15:00:00Z")});
db.access.save({user_id:'A001',status:200,create_dt:ISODate("2013-06-13T15:00:00Z")});
db.access.save({user_id:'A001',status:300,create_dt:ISODate("2013-06-13T15:00:00Z")});
db.access.save({user_id:'A002',status:200,create_dt:ISODate("2013-06-13T15:00:00Z")});
db.access.save({user_id:'A002',status:300,create_dt:ISODate("2013-06-13T15:00:00Z")});
この4日間のアクセスログ(もどき)を使って解析処理を行います。
test.js
var colName = 'access.status';
var map = function() {
var status = this.status;
var time = Date.parse(this.create_dt);
var dt = new Date();
dt.setTime(time);
var label = dt.getFullYear().toString() +
'-' +
dt.getMonth().toString() +
'-' +
dt.getDate().toString();
emit(
label,
{user_id: this.user_id, status: status}
);
}
//1日に置ける200の投稿率
var reduce = function(key, values) {
var users = {};
var result = {n: 0,count: 0};
values.forEach(function(value) {
if (!users[value.user_id]) {
users[value.user_id] = [];
}
users[value.user_id].push(value.status);
});
for (var user_key in users) {
var statuses = users[user_key];
var flg_200 = false;
var flg_300 = false;
var flg_500 = false;
result.n ++;
for (var status_key in statuses) {
var status = statuses[status_key];
if (status == 200) {
flg_200 = true;
}
if (status == 300) {
flg_300 = true;
}
if (status == 500) {
flg_500 = true;
}
};
//200:true, 300:true, 500:false
if (flg_200 && flg_300 && !flg_500) {
result.count ++;
}
};
return result;
}
var finalize = function(key, value) {
return {
'ユーザ数': value.n,
'合格数': value.count,
'合格率': (value.count / value.n * 100) + '%'
};
}
mongo = new Mongo('localhost');
mydb = mongo.getDB('nginx');
var res = mydb.access.mapReduce(map, reduce, {finalize: finalize,out: colName});
shellPrint(res);
はい、完了では
$ mongo test.js
$ mongo
> use nginx
switched to db nginx
> db.access.status.find();
{ "_id" : "2013-5-11", "value" : { "ユーザ数" : 3, "200:true, 300:true, 500:falseを通過した人数" : 2, "ユーザ数における通過率" : "66.66666666666666%" } }
{ "_id" : "2013-5-12", "value" : { "ユーザ数" : 7, "200:true, 300:true, 500:falseを通過した人数" : 3, "ユーザ数における通過率" : "42.857142857142854%" } }
{ "_id" : "2013-5-13", "value" : { "ユーザ数" : 2, "200:true, 300:true, 500:falseを通過した人数" : 0, "ユーザ数における通過率" : "0%" } }
{ "_id" : "2013-5-14", "value" : { "ユーザ数" : 2, "200:true, 300:true, 500:falseを通過した人数" : 2, "ユーザ数における通過率" : "100%" } }
決行色々出来そうだと思いました。
近いうちにnginxの生ログをなんかしら解析してまとめてみます。