Recherche facettée avec MongoDB
La recherche facettée avec MongoDB évolue avec la sortie de la version 3.4. Concrètement, cette recherche (faceted search) permet aux utilisateurs de filtrer une collection de données selon un ou plusieurs critères (les facettes). C’est exactement ce qui vous permet de trouver Batman parmi les super-héros en fonction de son univers (DC), sa ville (Gotham) et son symbole (chauve-souris).
Méthode 1 : La Brute
Le document contient des données en double car il faut dupliquer les données des facettes. Chaque document devient donc plus lourd. De plus, l’index est plus lourd qu’avec les autres méthodes.
// stockage
{
_id: 123,
name: "Batman",
universe: ["DC"],
city : [ "Gotham", "Arkham" ],
symbol : ["bat","cape"]
facets : [
"universe:DC",
"city:Gotham",
"city:Arkham",
"symbol:bat",
"symbol:cape"
]
}
// creation index
db.superheros.ensureIndex({"facets" : 1})
// obtenir les facettes
db.superheros.aggregate([{ "$unwind" : "$facets" },
{ "$group" : { "name" : "$facets", count : { "$sum" : 1 } } },
{ "$sort" : { "name" : 1 } }
])
Méthode 2 : Le Truand
Le document reste simple et devient même plus concis. Il faut créer un index par facette, pourtant le poids des index est inférieur à celui de l’index de la méthode 1. Par contre il est nécessaire de faire une aggrégation par facette.
réécrire en explosant les facettes et tester. ?
// stockage
{
_id: 123,
name: "Batman",
facets : {
universe: ["DC"],
city : [ "Gotham", "Arkham" ],
symbol : ["bat","cape"]
}
}
// creation index
db.superheros.ensureIndex({"facets.universe" : 1})
db.superheros.ensureIndex({"facets.city" : 1})
db.superheros.ensureIndex({"facets.symbol" : 1})
// obtenir les facettes
db.superheros.aggregate([{ "$unwind" : "$facets.universe" },
{ "$group" : { "name" : "$facets.universe", count : { "$sum" : 1 } } },
{ "$sort" : { "name" : 1 } }
])
db.superheros.aggregate([{ "$unwind" : "$facets.city" },
{ "$group" : { "name" : "$facets.city", count : { "$sum" : 1 } } },
{ "$sort" : { "name" : 1 } }
])
db.superheros.aggregate([{ "$unwind" : "$facets.symbol" },
{ "$group" : { "name" : "$facets.symbol", count : { "$sum" : 1 } } },
{ "$sort" : { "name" : 1 } }
])
Méthode 3 : Le Bon
Parmi les nouveautés de la version 3.4 de MongoDB, vous trouverez $facet et $bucket qui facilite la gestion des facettes. Le document n’est pas modifié pour les facettes. Aucun index spécifique n’est requis pour fonctionner.
// stockage
{
_id: 123,
name: "Batman",
universe: ["DC"],
city : [ "Gotham", "Arkham" ],
item : ["bat", "cape"]
}
// obtenir les facettes
db.superheros.aggregate( [
{
$facet: {
"categorizedByUniverse": [
{ $unwind: "$universe" },
{ $sortByCount: "$universe" }
],
"categorizedByCities": [
{ $unwind: "$city" },
{ $sortByCount: "$city" }
],
"categorizedByItems": [
{ $unwind: "$item" },
{ $sortByCount: "$item" }
]
}
}
])
Astuce
Pour connaitre les versions de MongoDB, voici deux commandes à exécuter dans le shell mongo :
version() : connaitre la version du client MongoDB
db.version() : connaitre la version de MongoDB
Références