Cara Query dengan GROUP BY di MongoDB

Di MySQL kita dapat dengan mudahnya mengeksekusi query hanya dengan sintaks GROUP BY. Tapi bagaimana cara mengeksekusinya di MongoDB?

Sama mudahnya!

Contoh di console:


db.coll.group({
    key: { a:true, b:true },
    cond: { active:1 },
    reduce: function(obj,prev) { prev.csum += obj.c; },
    initial: { csum: 0 }
});

Contoh di PHP:

$db = new Mongo("mongodb://localhost");

$key = array (
	'a'	=> TRUE,
	'b'	=> TRUE,
);

$initial = array (
	'active' => 1
);

$reduce = new MongoCode ("
	function(obj,prev) {
		prev.csum += obj.c;
	}
");

$condition = array (
	'active'	=> 1
);

$result = $db->coll->group (
	$key,
	$initial,
	$reduce,
	$condition
);

Contoh Kasus

Analytics Website dengan Mongo

Anda memiliki data analytics sederhana untuk website anda sendiri. Yang mencatat berapa banyak sebuah artikel dibaca per hari. Yang tersedia adalah dua collection, pageview dan pagelog. Collection Pageview menyimpan data jumlah total berapa halaman itu terbaca, dan Pagelog menyimpan log setiap kali sebuah halaman diakses oleh orang lain.

Pageview berguna untuk mengambil data berapa total sebuah halaman dibaca dalam rentang waktu keseluruhan, sementara dengan pagelog, data dapat diolah untuk mendapatkan berapa kali sebuah halaman diakses dalam rentang waktu tertentu.

Contoh data:


db.createCollection("pageview");
db.createCollection("pagelog");


db.pagelog.insert ({
	url:'http://abetobing.com/about',
	created:new Date().getTime()
});
db.pageview.update (
	{url:'http://abetobing.com/about'},
	{
		$inc: {
			view:1
		}
	},
	true // upsert mode
);

Contoh diatas adalah proses insert data pageview dan pagelog ke collection.
Di collection pagelog, di sertakan field url dan created. Url menyimpan data alamat
web yang dikunjungi, dan created adalah data waktu sebuah halaman dikunjungi dalam format timestamp.

Sedangkan pada collection pageview, data dimasukkan dengan metode upsert. Yaitu, tambahkan nilai view dengan angka 1, dan jika data belum ada, maka create data tersebut di dalam collection.

Selanjutnya kita akan melakukan mass insert ke database agar kita dapat mengolah data lebih baik saat melakukan grouping nanti.


db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/blog', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/blog'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/blog', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/blog'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/about', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/about'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/portfolio', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/portfolio'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/portfolio', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/portfolio'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/portfolio', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/portfolio'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/portfolio', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/portfolio'}, {$inc: {view:1}}, true);
db.pagelog.insert ({url:'http://abetobing.com/contact', created:new Date().getTime()});
db.pageview.update ({url:'http://abetobing.com/contact'}, {$inc: {view:1}}, true);

Pada kode diatas, kita memasukkan tiga halaman dari website ini ke database analytics sederhana.
Tiga halaman itu adalah

http://abetobing.com/about
http://abetobing.com/blog
http://abetobing.com/portfolio
http://abetobing.com/contact

Kasusnya adalah bagaimana mendapatkan jumlah berapa kali terbaca dalam waktu tertentu?


var now = new Date().getTime();
var lastOneDay = now - (3600 * 24); // satu hari yang lalu
db.pagelog.group ({
	key: {url:true},
	reduce: function (data, output) {
		output.count++;
		output.url = data.url;
	},
	initial: {count:0, url:''}
});

Outputnya kurang lebih seperti ini:


[
	{
		"url" : "http://abetobing.com/about",
		"count" : 7
	},
	{
		"url" : "http://abetobing.com/blog",
		"count" : 2
	},
	{
		"url" : "http://abetobing.com/portfolio",
		"count" : 4
	},
	{
		"url" : "http://abetobing.com/contact",
		"count" : 1
	}
]

Dari contoh diatas kita telah berhasil meng-grouping query dari mongo berdasar url-nya serta menjumlahkan berapa banyak url tersebut di lihat pengunjung dalam rentang waktu tertentu.

Implementasi Dalam Format PHP

Kurang lebih beginilah jika contoh diatas diterjemahkan ke PHP

$db = new Mongo("mongodb://localhost");
$lastOneDay = time() - (3600*24); // last one day

$key = array (
	'url'	=> TRUE,
);

$initial = array (
	'count' => 0,
	'url'	=> '',
);

$reduce = new MongoCode ("
	function(data, output) {
		output.count++;
		output.url = data.url;
	}
");

$condition = array (
	'created' => array (
		'$gt' => $lastOneDay
	)
);

$result = $db->coll->group (
	$key,
	$initial,
	$reduce,
	$condition
);

print_r ($result);

Selamat Bermongo