Requêtes textuelles et géo-spatiales

Planche de TD pour un cours dispensé à  l’université de Rennes 2

Romain Tavenard

1 Requêtes textuelles

Pour cette partie, vous travaillerez sur la base elections2007.

1.1 Expressions régulières

Lorsque l’on souhaite interroger des champs textuels, il existe, en plus des outils précédemment introduits, deux méthodes spécifiques :

  1. l’utilisation d’expressions régulières ;
  2. le recours à  un index textuel qui permet d’effectuer des recherches de type “moteur de recherche”.

Les expressions régulières sont des moyens de mettre des contraintes sur les chaînes de caractères acceptables. Parmi ces contraintes, on peut citer :

En langage MongoDB, une requête utilisant une expression régulière sera de la forme :

> db.nomDeLaCollection.find({"cle": /blabla/})
  1. Affichez la liste des discours pour lesquels l’orateur a un prénom qui commence par la lettre J.

  2. Affichez la liste des discours pour lesquels l’orateur a un nom qui se termine par la chaîne "et".

  3. Affichez la liste des discours pour lesquels l’orateur a un nom qui commence par la lettre S.

  4. Affichez la liste des discours pour lesquels l’orateur a un prénom composé.

1.2 Requêtes de type “moteur de recherche”

Dans certains cas, on souhaitera chercher dans des champs textuels comme on le ferait à  l’aide d’un moteur de recherche. Pour cela, il faut qu’un index spécifique soit mis en place sur le champ en question.

  1. Vérifiez qu’un tel index existe.

Lorsqu’un tel index existe, MongoDB saura que c’est sur le champ correspondant qu’il faudra effectuer les requêtes textuelles et il ne sera donc plus utile de le préciser. On obtiendra alors une requête de la forme :

> db.nomDeLaCollection.find({$text : {$search : "ma requête"}})

Par défaut, lorsque l’on effectue une requête contenant plusieurs termes, un OU logique est effectué : les documents retournés sont ceux qui contiennent au moins l’un des termes. On peut également effectuer une requête impliquant une expression exacte, qui sera encadrée de guillemets échappés par un caractère "\" :

> db.nomDeLaCollection.find({$text : {$search : "\"ma requête\""}})

Enfin, on peut exclure les documents contenant certains termes en précédant chacun de ces termes par le symbole "-". Toutefois, si l’on mélange plusieurs types de conditions, un ET logique est effectué entre les différents types, comme par exemple :

Par exemple, la requête suivante retournera tous les documents contenant le terme "bla" ET ne contenant pas le terme "bli" :

> db.nomDeLaCollection.find({$text : {$search : "bla -bli"}})

Enfin, il est possible d’afficher les scores (type tf-idf) obtenus par les différents documents à  l’aide de la commande :

> db.nomDeLaCollection.find({$text: {$search: "ma requête"}},
                            {"score": {$meta: "textScore"}})

Dans ce cas, il sera souvent utile de trier les résultats par ordre de pertinence décroissante :

> db.nomDeLaCollection.find({$text: {$search: "ma requête"}},
                            {"score": {$meta: "textScore"}}).sort(
                                {score: {$meta: "textScore"}})
  1. Affichez la liste des documents contenant l’expression exacte suivante : "l'effet sera nul".

  2. Affichez la liste des discours dans lesquels ont été prononcés :

  1. Vérifiez que les scores retournés dans la deuxième requête de la question précédente tendent à  favoriser les documents contenant les deux termes (les autres documents ont des scores plus faibles).

  2. Affichez la liste des documents comportant le terme "famille" mais pas le terme "politique".

2 Requêtes géo-spatiales

Dans le cas de données géo-spatiales, on peut avoir à  effectuer des requêtes spécifiques, comme par exemple :

Pour cela, il faut tout d’abord s’assurer qu’un index géo-spatial (de type 2dsphere pour des coordonnées à  la surface de la terre) existe sur le champ visé.

  1. Vérifiez qu’un index géo-spatial existe sur l’un des champs de la collection NYfood de la base food.

MongoDB définit trois mots-clés correspondant aux situations définies précédemment :

La syntaxe correspondante est toujours de la même forme (remplacer $near par $within au besoin) :

> db.nomDeLaCollection.find({"clé": {$near : {$geometry : ref}}})

ref est une variable correspondant à  la référence à  laquelle on souhaite se comparer :

> var ref = {"type": "Point", "coordinates": [longitude, latitude]}
> var ref = {"type": "Polygon", "coordinates": [[[long1, lat1],
                                                 [long2, lat2],
                                                 [long3, lat3],
                                                 [long4, lat4],
                                                 [long1, lat1]]]}

Ainsi, il faudra veiller à  ce que les polygones que vous créez sont bien fermés (les dernières coordonnées sont égales aux premières).

  1. Trouver les restaurants les plus proches de Crown Heights (supposé ponctuel de coordonnées approximatives [-73.923, 40.676]).

  2. Trouver les restaurants chinois les plus proches de Crown Heights.

  3. Même question en ne conservant que les restaurants situés à  moins de 500m de Crown Heights (voir la doc MongoDB si besoin).

  4. Trouver tous les restaurants du quartier d’East Village à  New York (vous pourrez utiliser Google Maps pour connaître les coordonnées du polygone entourant ce quartier).