Image
Haut
Découvrez le site de La Belle Assiette
Navigation
25 juin 2013

Premiers pas avec l’agrégation

Dans le dernier article, j'ai rapidement montré que sur une certaine opération, l'agrégation était plus rapide que les méthodes.
Faisons un tour d'horizon des possibilités du Framework.

group_group

Grouper des données

Imaginons que nous avons développé un blog.
Un article est représenté par un document.

{
	createdDate: Date,
	author: Sting,
	title: String,
	content: String
}

Si nous souhaitons connaitre le nombre d'articles par author il nous suffirait d'utiliser la pipeline $group

db.posts.aggregate({
	$group: {
		_id: '$author',
		count: {$sum: 1}
	}
})

_id est l'attribut principal.
Obligatoire, il nous permet de spécifier par quel attribut nous souhaitons grouper.
On remarque que c'est le String de l'attribut précédé d'un $.
Tous les '$KEY' serons des références au document initial.

count sera présent dans notre resultat. le $sum signifie que pour chaque document du groupe, count sera additionné par la valeur suivante (ici 1).
En gros, on incrémante notre count.

Maintenant, nous aimerions avoir en plus un tableau des contenus/title/date de créations.
Nous allons push dans un tableau chaque élément du groupe.

db.posts.aggregate({
	$group: {
		_id: '$author',
		posts: {$push: {createdDate: '$createdDate', title: '$title', content: '$content'}}
	}
})

Grouper par mois

Utiliser un timestamp ou un Date est parfait pour la date.
Nous pouvons sans peine extraire le mois pour grouper.

db.posts.aggregate({
	$group: {
		_id: {
			month: {$month: '$createdDate'},
			year: {$year: '$createdDate'}
		},
		count: {$sum: 1}
	}
})

Selectionner les données a groupé

Bien sur, il est possible de sélectionner qu'une partie des données a groupé avec la pipeline $match.

db.posts.aggregate({
	$match: {
		author: {$in: ['Loutre', 'Mulot']}
	}
},
{
	$group: {
		_id: '$author',
		count: {$sum: 1}
	}
})

Nous pouvons utiliser dans $match toutes les queries possibles avec MongoDb.
A savoir que l'ordre des pipeline est importante. Il est préférable d'utiliser le $match tout au début pour profiter des indexes et limiter les données a traité par la suite.
Nous verrons que l'ordre du pipeline $sort est importante et permet de d'ordonner finement nos données.

Le cas des commentaires

Ajoutons des commentaires à nos articles. Stockons un tableau de commentaires dans notre document.

{
	createdDate: Date,
	author: Sting,
	title: String,
	content: String,
	comments: [{
		date: Date,
		writer: String,
		role: String,
		msg: String
	}]
}

Si nous souhaitons connaitre le nombre de commentaire du blog nous allons devoir utiliser le pipeline $unwind
$unwind nous permet d'éclater un tableau en documents.

db.posts.aggregate({
	$unwind: '$comments'
})

Le résultat sera un tableau des articles avec un seul commentaire.

Nous pouvons limiter le nombre de résultat avec le pipeline $limit
Attention, l'ordre des pipeline est important.

Groupons les commentaires

Pour aller encore plus loin, nous souhaitons le nombre de commentaire PAR articles.
Il nous suffit d'utiliser $unwind pour éclater les commentaires, puis $group pour les re-grouper par articles.

db.posts.aggregate({
	$unwind: '$comments'
}, {
	$group: {
		_id: '$_id'
		count: {$sum: 1}
	}
})

Ici '$_id' est l'id du document d'où provient le commentaire

Maintenant, soyons fous, groupons par auteur !

db.posts.aggregate({
	$unwind: '$comments'
}, {
	$group: {
		_id: '$writer',
		count: {$sum: 1}
	}
})

Tous pour la fin

Enfin pour un vrai blog, nous aimerions avoir tous les articles de "Loutre" triés par date du plus récent au plus ancien, avec les commentaires du plus ancien au plus récent.

db.posts.aggregate({
	$match: {
		author: 'Loutre'
	}
}, {
	$unwind: '$comments'
}, {
	$sort: {date: -1}
}, {
	$group: {
		_id: {
			autor: '$author',
			title: '$title',
			content: '$content',
			createdDate: '$createdDate'
		},
		comments: {
			$push: '$comments'
		}
	}
}, {
	$sort: {createdDate: 1}
})

final_aggregation

Conclusion

Voilà un bon tour d'horizons des possibilités du framework d'agrégation.
Nous n'avons pas vu les possibilités du pipeline $project ni celle offertes sur des données geo-spatiales ( $geonear par exemple)

Enfin il reste des operateurs fort utile pour $group

N'hésitez pas à expérimenter vous-même !

Cet article vous a intéressé ? Recevez les prochains par email:





Commentaires

Envoyer un commentaire

Écrit par

Catégories

Les nouveautés