cours-2023-2024 | Documents de mes cours pour l'année 2023-2024 | FX Jollois

Premiers pas sur Mongo

Présentation de MongoDB

Base de données NoSQL de type Document Store (orienté document)

Objectifs :

Plus d’informations sur leur site

Modèle des données

Principe de base : les données sont des documents

Format JSON

Validation possible du JSON sur jsonlint.com/

Exemple de JSON

{
    "address": {
        "building": "469",
        "coord": [
            -73.9617,
            40.6629
        ],
        "street": "Flatbush Avenue",
        "zipcode": "11225"
    },
    "borough": "Brooklyn",
    "cuisine": "Hamburgers",
    "grades": [
        {
            "date": "2014-12-30 01:00:00",
            "grade": "A",
            "score": 8
        },
        {
            "date": "2014-07-01 02:00:00",
            "grade": "B",
            "score": 23
        }
    ],
    "name": "Wendy'S",
    "restaurant_id": "30112340"
}

Compléments

BSON : extension de JSON

Schéma dynamique

Langage d’interrogation

Interaction entre Python et MongoDB

Utilisation du package pymongo

A l’IUT, Il faut l’installer via Anaconda Prompt, avec la ligne de commande suivante

$ pip install pymongo[srv]

Connexion à un serveur distant

import pymongo
URI = 'mongodb+srv://user:user@cluster0.ougec.mongodb.net/test'
client = pymongo.MongoClient(URI) # enlever le paramètre URI si connexion locale
db = client.test

Exemples sur restaurants

Dans ce document, nous allons travailler sur une base des restaurants New-Yorkais.

Voici le premier document est présenté ci-dessous sur les plus de 25000 restaurants new-yorkais (base de test fournie par Mongo)

{
        "_id" : ObjectId("58ac16d1a251358ee4ee87de"),
        "address" : {
                "building" : "469",
                "coord" : [
                        -73.961704,
                        40.662942
                ],
                "street" : "Flatbush Avenue",
                "zipcode" : "11225"
        },
        "borough" : "Brooklyn",
        "cuisine" : "Hamburgers",
        "grades" : [
                {
                        "date" : ISODate("2014-12-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 8
                },
                {
                        "date" : ISODate("2014-07-01T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                },
                {
                        "date" : ISODate("2013-04-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                },
                {
                        "date" : ISODate("2012-05-08T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                }
        ],
        "name" : "Wendy'S",
        "restaurant_id" : "30112340"
}

Document dans python

Les données JSON sont similaires à un dictionnaire python. Pour récupérer le premier document, nous utilisons la fonction find() de l’objet créé m.

d = db.restaurants.find(limit = 1)
d

L’objet retourné est un curseur, et non le résultat. Nous avons celui-ci lorsque nous utilisons d dans une commande telle qu’une transformation en list par exemple.

list(d)

Une fois le résultat retourné (un seul élément ici), le curseur ne renvoie plus rien.

list(d)

Dénombrement

Tous les restaurants

db.restaurants.count_documents({})
db.restaurants.estimated_document_count()

Sélection de documents

Pour sélectionner les documents, nous allons utiliser le paramètre dans la fonction count_documents() (ainsi que dans les fonctions distinct() et find() que nous verrons plus tard).

Comptage de certains documents

db.restaurants.count_documents({ "borough": "Brooklyn" })
db.restaurants.count_documents({ "borough": "Brooklyn", "cuisine": "French" })

Comptage de certains documents (suite)

db.restaurants.count_documents({ "borough": "Brooklyn", "cuisine": { "$in": ["French", "Italian"]} })
db.restaurants.count_documents(
  { 
    "borough": "Brooklyn", 
    "cuisine": { "$in": ["French", "Italian"]}
  }
)

Comptage de certains documents (suite)

db.restaurants.count_documents(
  { 
    "address.street": "Franklin Street"
  }
)
db.restaurants.count_documents(
  { 
    "grades.score": 0
  }
)

Comptage de certains documents

db.restaurants.count_documents(
  { 
    "grades.score": { "$lte": 5 }
  }
)

Valeurs distinctes

On peut aussi voir la liste des valeurs distinctes d’un attribut, avec la fonction distinct().

db.restaurants.distinct(key = "borough")

Valeurs distinctes (suite)

db.restaurants.distinct(
  key = "cuisine",
  query = { "borough": "Brooklyn" }
)

Valeurs distinctes (suite)

db.restaurants.distinct(
  key = "grades.grade",
  query = { "borough": "Brooklyn" }
)

Restriction et Projection

Sélection de champs à afficher ou non

Dans la fonction find(), pour choisir les champs à afficher, le deuxième paramètre permet de faire une projection avec les critères suivants :

Tri et limite

Toujours dans la fonction find(), il est possible de faire le tri des documents, avec le paramètre sort qui prend un tuple composé de 1 ou plusieurs tuples indiquant les critères de tri

Dans ces fonctions, on peut aussi limiter l’exploration à une partie, avec les paramètres suivant :

Récupération des 5 premiers documents

Notez le contenu des colonnes address et grades.

import pandas
pandas.DataFrame(list(db.restaurants.find(limit = 5)))

Récupération de documents (suite)

c = db.restaurants.find({ "name": "Shake Shack" }, { "address.street": 1, "borough": 1 })
pandas.DataFrame(list(c))

Récupération de documents (suite)

c = db.restaurants.find(
    { "name": "Shake Shack" }, 
    { "_id": 0, "address.street": 1, "borough": 1 }
)
pandas.DataFrame(list(c))

Récupération de documents (suite)

c = db.restaurants.find(
    {"borough": "Queens", "grades.score": { "$gte":  50}},
    {"_id": 0, "name": 1, "grades.score": 1, "address.street": 1},
    limit = 5
)
pandas.DataFrame(list(c))

Récupération de documents (suite)

c = db.restaurants.find(
    {"name": "Shake Shack", "borough": {"$in": ["Queens", "Brooklyn"]}}, 
    {"_id": 0, "address.street": 1, "borough": 1}
)
pandas.DataFrame(list(c))

Récupération de documents (suite)

c = db.restaurants.find(
    {"borough": "Queens", "grades.score": { "$gt":  50}},
    {"_id": 0, "name": 1, "address.street": 1},
    sort = (("address.street", -1), ("name", 1))
)
pandas.DataFrame(list(c))

A faire

  1. Donner les styles de cuisine présent dans la collection
  2. Donner tous les grades possibles dans la base
  3. Compter le nombre de restaurants proposant de la cuisine fraçaise (“French”)
  4. Compter le nombre de restaurants situé sur la rue “Central Avenue”
  5. Compter le nombre de restaurants ayant eu une note supérieure à 50
  6. Lister tous les restaurants, en n’affichant que le nom, l’immeuble et la rue
  7. Lister tous les restaurants nommés “Burger King” (nom et quartier uniquement)
  8. Lister les restaurants situés sur les rues “Union Street” ou “Union Square”
  9. Lister les restaurants situés au-dessus de la lattitude 40.90
  10. Lister les restaurants ayant eu un score de 0 et un grade “A”

Questions complémentaires

Nécessitent une recherche sur la toile pour compléter ce qu’on a déjà vu dans ce TP.

  1. Lister les restaurants (nom et rue uniquement) situés sur une rue ayant le terme “Union” dans le nom
  2. Lister les restaurants ayant eu une visite le 1er février 2014
  3. Lister les restaurants situés entre les longitudes -74.2 et -74.1 et les lattitudes 40.1 et 40.2