Introduction à MongoDB et Python – Real Python

By | mars 1, 2021

Cours Python en ligne

Python est un langage de programmation puissant utilisé pour de nombreux types d'applications au sein de la communauté de développement. Beaucoup le savent comme un langage flexible qui peut gérer à peu près n'importe quelle tâche.

Alors, que se passe-t-il si notre application Python complexe a besoin d'une base de données aussi flexible que le langage lui-même?

C'est là que NoSQL, et plus particulièrement MongoDB, entrent en jeu.

Tout au long de cet article, nous vous montrerons comment utiliser Python pour s'interfacer avec la base de données populaire MongoDB (v3.4.0), ainsi qu'un aperçu de SQL vs NoSQL, PyMongo (v3.4.0) et MongoEngine (v0.10.7), entre autres.

SQL contre NoSQL

Au cas où vous ne le seriez pas familier, MongoDB est une base de données NoSQL qui est devenue très populaire dans l’industrie ces dernières années. Les bases de données NoSQL fournissent des fonctionnalités de récupération et de stockage de données d'une manière très différente de leurs homologues de bases de données relationnelles.

Pendant des décennies, les bases de données SQL ont été l'un des seuls choix pour les développeurs cherchant à créer des systèmes volumineux et évolutifs. Cependant, le besoin toujours croissant de capacité à stocker des structures de données complexes a conduit à la naissance de bases de données NoSQL, qui permettent à un développeur de stocker des données hétérogènes et sans structure.

En ce qui concerne les choix disponibles, la plupart des gens doivent se poser la question ultime, «SQL ou NoSQL?» SQL et NoSQL ont tous deux leurs forces et leurs faiblesses, et vous devez choisir celui qui correspond le mieux aux exigences de votre application. Voici quelques différences entre les deux:

SQL

  • Le modèle est de nature relationnelle
  • Les données sont stockées dans des tables
  • Convient aux solutions où chaque enregistrement est du même type et possède les mêmes propriétés
  • L'ajout d'une nouvelle propriété signifie que vous devez modifier tout le schéma
  • Le schéma est très strict
  • Les transactions ACID sont prises en charge
  • Échelle bien verticalement

NoSQL

  • Le modèle est non relationnel
  • Peut être stocké au format JSON, clé-valeur, etc. (selon le type de base de données NoSQL)
  • Tous les enregistrements ne doivent pas nécessairement être de la même nature, ce qui les rend très flexibles
  • Ajoutez de nouvelles propriétés aux données sans rien déranger
  • Aucune exigence de schéma à respecter
  • La prise en charge des transactions ACID peut varier en fonction de la base de données NoSQL utilisée
  • La cohérence peut varier
  • Échelle bien horizontalement

Il existe de nombreuses autres différences entre les deux types de bases de données, mais celles mentionnées ci-dessus sont quelques-unes des différences les plus importantes à connaître.

Selon votre scénario spécifique, l'utilisation d'une base de données SQL peut être préférée, tandis que dans d'autres scénarios, NoSQL est le choix le plus évident à faire. Lors du choix d'une base de données, vous devez considérer attentivement les forces et les faiblesses de chaque base de données.

L'un des avantages de NoSQL est qu'il existe de nombreux types de bases de données parmi lesquels choisir, et chacune a ses propres cas d'utilisation:

Il y en a beaucoup plus, mais ce sont quelques-uns des types les plus courants.

Ces dernières années, les bases de données SQL et NoSQL ont même commencé à fusionner. Par exemple, PostgreSQL prend désormais en charge le stockage et l'interrogation des données JSON, un peu comme Mongo. Avec cela, vous pouvez désormais obtenir la même chose avec Postgres qu'avec Mongo, mais vous ne bénéficiez toujours pas de nombreux avantages de Mongo (comme la mise à l'échelle horizontale et l'interface simple, etc.). Comme le dit cet article:

Si vos données actives s'inscrivent confortablement dans le schéma relationnel et que le contenu JSON est une cohorte de ces données, vous devriez être d'accord avec PostgreSQL et ses capacités de représentation et d'indexation JSONB sont beaucoup plus efficaces. Si cependant, votre modèle de données est celui d'une collection de documents mutables, vous voudrez probablement regarder une base de données conçue principalement autour de documents JSON comme MongoDB ou RethinkDB.

MongoDB

Portons maintenant notre attention sur l'objectif principal de cet article et éclairons les spécificités de MongoDB.

MongoDB est un programme de base de données open source orienté document, indépendant de la plate-forme. MongoDB, comme certaines autres bases de données NoSQL (mais pas toutes!), Stocke ses données dans des documents en utilisant une structure JSON. C'est ce qui permet aux données d'être si flexibles et de ne pas nécessiter de schéma.

Certaines des caractéristiques les plus importantes sont:

  • Vous avez la prise en charge de nombreux types de requêtes standard, comme la correspondance (==), Comparaison (<, >), ou même regex
  • Vous pouvez stocker pratiquement n'importe quel type de données – qu'elles soient structurées, partiellement structurées ou même polymorphes
  • Pour augmenter et gérer plus de requêtes, ajoutez simplement plus de machines
  • Il est très flexible et agile, vous permettant de développer rapidement vos applications
  • Être une base de données documentaire signifie que vous pouvez stocker toutes les informations concernant votre modèle dans un seul document
  • Vous pouvez modifier le schéma de votre base de données à la volée
  • De nombreuses fonctionnalités de bases de données relationnelles sont également disponibles dans MongoDB (par exemple, l'indexation)

En ce qui concerne les opérations, il existe de nombreux outils et fonctionnalités pour MongoDB que vous ne pouvez trouver avec aucun autre système de base de données:

  • Que vous ayez besoin d'un serveur autonome ou de clusters complets de serveurs indépendants, MongoDB est aussi évolutif que vous en avez besoin.
  • MongoDB fournit également une prise en charge de l'équilibrage de charge en déplaçant automatiquement les données entre les différentes partitions
  • Il prend en charge le basculement automatique – au cas où votre serveur principal tomberait en panne, un nouveau principal sera opérationnel et fonctionnera automatiquement
  • Le service de gestion MongoDB ou MMS est un très bel outil Web qui vous permet de suivre vos machines
  • Grâce aux fichiers mappés en mémoire, vous économiserez pas mal de RAM, contrairement aux bases de données relationnelles

Si vous tirez parti des fonctionnalités d'indexation, la plupart de ces données seront conservées en mémoire pour une récupération rapide. Et même sans indexation sur des clés de document spécifiques, Mongo met en cache pas mal de données en utilisant la méthode la moins récemment utilisée.

Si au premier abord Mongo peut sembler être la solution à bon nombre de nos problèmes de base de données, ce n’est pas sans inconvénients. Un inconvénient courant que vous entendrez à propos de Mongo est son manque de prise en charge des transactions ACID. Mongo Est-ce que prend en charge les transactions ACID dans un sens limité, mais pas dans tous les cas. Au niveau du document unique, les transactions ACID sont prises en charge (c'est là que la plupart des transactions ont lieu de toute façon). Cependant, les transactions portant sur plusieurs documents ne sont pas prises en charge en raison de la nature distribuée de Mongo.

Mongo ne prend pas non plus en charge les jointures natives, qui doivent être effectuées manuellement (et donc beaucoup plus lentement). Les documents sont censés être complets, ce qui signifie qu’en général, ils ne devraient pas avoir besoin de faire référence à d’autres documents. Dans le monde réel, cela ne fonctionne pas toujours car la plupart des données avec lesquelles nous travaillons sont relationnelles par nature. Par conséquent, beaucoup diront que Mongo devrait être utilisé comme base de données complémentaire à une base de données SQL, mais lorsque vous utilisez MongoDB, vous constaterez que ce n'est pas nécessairement vrai.

PyMongo

Maintenant que nous avons décrit ce qu'est exactement MongoDB, voyons comment vous l'utiliseriez réellement avec Python. Le pilote officiel publié par les développeurs Mongo s'appelle PyMongo. C'est un bon point de départ lors du premier lancement de Python avec MongoDB. Nous allons passer en revue quelques exemples ici, mais vous devriez également consulter la documentation complète car nous ne pourrons pas tout couvrir.

La première chose à faire est d’installer PyMongo dans votre environnement virtuel. Le moyen le plus simple de le faire est d'utiliser pépin:

$ installation de pip pymongo==3.4.0

REMARQUE: Pour un guide plus complet, consultez la page Installation / Mise à jour de la documentation et suivez les étapes pour vous y installer.

Une fois la configuration terminée, démarrez votre console Python et exécutez la commande suivante:

S'il s'exécute sans lever d'exception dans le shell Python, votre installation a parfaitement fonctionné. Sinon, recommencez soigneusement les étapes. Quittez le shell une fois terminé.

Ensuite, vous devez installer la base de données MongoDB.

Si vous utilisez un Mac, nous vous recommandons d'utiliser Homebrew, mais vous pouvez avoir une préférence différente. Si vous utilisez Homebrew, exécutez cette commande:

Une fois terminé, suivez les instructions ici pour configurer le répertoire de données pour stocker les données localement.

Si vous n'utilisez pas de Mac, vous pouvez trouver d'excellents guides d'installation sur la page Installer MongoDB de la documentation officielle. Vous y trouverez des didacticiels sur l'installation de MongoDB pour Linux, OS X et Windows.

Une fois installé, dans une nouvelle fenêtre de terminal, utilisez la commande suivante pour démarrer le démon Mongo:

REMARQUE: En fonction de votre méthode d'installation, vous devrez peut-être exécuter Mongod avec sudo.

Commençons maintenant avec les bases de PyMongo.

Établir une connexion

Pour établir une connexion, nous utiliserons le MongoClient objet.

La première chose que nous devons faire pour établir une connexion est d'importer le MongoClient classer. Nous l'utiliserons pour communiquer avec l'instance de base de données en cours d'exécution. Utilisez le code suivant pour ce faire:

de pymongo importer MongoClient
client = MongoClient()

En utilisant l'extrait de code ci-dessus, la connexion sera établie avec l'hôte par défaut (localhost) et port (27017). Vous pouvez également spécifier l'hôte et / ou le port en utilisant:

client = MongoClient('localhost', 27017)

Ou utilisez simplement le format d'URI Mongo:

client = MongoClient(«mongodb: // localhost: 27017»)

Tous ces appels à MongoClient fera la même chose; cela dépend simplement de la manière dont vous voulez être explicite dans votre code.

Accéder aux bases de données

Une fois que vous avez une instance connectée de MongoClient, vous pouvez accéder à l'une des bases de données de ce serveur Mongo. Pour spécifier la base de données que vous souhaitez réellement utiliser, vous pouvez y accéder en tant qu'attribut:

Ou vous pouvez également utiliser l'accès de style dictionnaire:

db = client[[[['pymongo_test']

Peu importe si votre base de données spécifiée a déjà été créée. En spécifiant ce nom de base de données et en y enregistrant des données, vous créez la base de données automatiquement.

Insérer des documents

Stocker des données dans votre base de données est aussi simple que d'appeler seulement deux lignes de code. La première ligne spécifie la collection que vous utiliserez (des postes dans l'exemple ci-dessous). Dans la terminologie MongoDB, une collection est un groupe de documents qui sont stockés ensemble dans la base de données. Les collections et les documents s'apparentent respectivement aux tables et aux lignes SQL. Récupérer une collection est aussi simple que d'obtenir une base de données.

La deuxième ligne est l'endroit où vous insérez réellement les données dans la collection en utilisant le insert_one () méthode:

des postes = db.des postes
post_data = 
    'Titre': 'Python et MongoDB',
    'teneur': 'PyMongo est amusant, vous les gars',
    'auteur': «Scott»

résultat = des postes.insert_one(post_data)
impression(Un message: 0'.format(résultat.insert_id))

Nous pouvons même insérer plusieurs documents à la fois, ce qui est beaucoup plus rapide que d'utiliser insert_one () si vous avez de nombreux documents à ajouter à la base de données. La méthode à utiliser ici est insert_many (). Cette méthode prend un tableau de données de document:

post_1 = 
    'Titre': 'Python et MongoDB',
    'teneur': 'PyMongo est amusant, vous les gars',
    'auteur': «Scott»

post_2 = 
    'Titre': «Environnements virtuels»,
    'teneur': «Utilisez des environnements virtuels, vous les gars»,
    'auteur': «Scott»

post_3 = 
    'Titre': 'Apprendre Python',
    'teneur': 'Apprenez Python, c'est facile',
    'auteur': 'Facture'

nouveau_résultat = des postes.insert_many([[[[post_1, post_2, post_3])
impression('Plusieurs messages: 0'.format(nouveau_résultat.insert_ids))

Lorsqu'il est exécuté, vous devriez voir quelque chose comme:

Un message: 584d947dea542a13e9ec7ae6
Plusieurs messages:[[[[
                ObjectId ('584d947dea542a13e9ec7ae7'),
                ObjectId ('584d947dea542a13e9ec7ae8'),
                ObjectId ('584d947dea542a13e9ec7ae9')
]

REMARQUE: Ne vous inquiétez pas que votre ObjectIdne correspondent pas à ceux indiqués ci-dessus. Ils sont générés dynamiquement lorsque vous insérez des données et se composent d'une époque Unix, d'un identifiant de machine et d'autres données uniques.

Récupération de documents

Pour récupérer un document, nous utiliserons le find_one () méthode. Le seul argument que nous utiliserons ici (bien qu'il en accepte de nombreux autres) est un dictionnaire qui contient des champs correspondants. Dans notre exemple ci-dessous, nous voulons récupérer le message qui a été rédigé par Facture:

factures_post = des postes.find_one('auteur': 'Facture')
impression(factures_post)

Lance ça:


                'author': 'Bill',
                'title': 'Apprendre Python',
                'content': 'Apprenez Python, c'est facile',
                '_id': ObjectId ('584c4afdea542a766d254241')

Vous avez peut-être remarqué que le message ObjectId est placé sous le _identifiant key, que nous pouvons utiliser ultérieurement pour l'identifier de manière unique si nécessaire. Si nous voulons trouver plus d'un document, nous pouvons utiliser le trouver() méthode. Cette fois, trouvons tous les articles rédigés par Scott:

scotts_posts = des postes.trouver('auteur': «Scott»)
impression(scotts_posts)

Courir:


La principale différence ici est que les données du document ne nous sont pas renvoyées directement sous forme de tableau. Au lieu de cela, nous obtenons une instance de l'objet Cursor. Ce Le curseur est un objet itérable qui contient plusieurs méthodes d'aide pour vous aider à travailler avec les données. Pour obtenir chaque document, parcourez simplement le résultat:

pour Publier dans scotts_posts:
    impression(Publier)

MongoEngine

Bien que PyMongo soit très facile à utiliser et globalement une excellente bibliothèque, il est probablement un peu trop bas niveau pour de nombreux projets. En d'autres termes, vous devrez écrire une grande partie de votre propre code pour régulièrement enregistrer, récupérer et supprimer des objets.

Une bibliothèque qui fournit une abstraction plus élevée au-dessus de PyMongo est MongoEngine. MongoEngine est un mappeur de document objet (ODM), qui équivaut à peu près à un mappeur relationnel d'objets basé sur SQL (ORM). L'abstraction fournie par MongoEngine est basée sur les classes, donc tous les modèles que vous créez sont des classes.

Bien que de nombreuses bibliothèques Python existent pour vous aider à travailler avec MongoDB, MongoEngine est l'une des meilleures car elle offre un bon mélange de fonctionnalités, de flexibilité et de support de la communauté sans devenir trop opiniâtre.

Pour installer, utilisez pépin:

$ installation de pip mongoengine==0.10.7

Une fois installé, nous devons diriger la bibliothèque pour qu'elle se connecte à notre instance en cours d'exécution de Mongo. Pour cela, nous devrons utiliser le relier() et passez-lui l'hôte et le port de la base de données MongoDB. Dans le shell Python, saisissez:

de mongoengine importer *
relier('mongoengine_test', héberger='localhost', Port=27017)

Ici, nous spécifions le nom de notre base de données et son emplacement. Étant donné que nous utilisons toujours l'hôte et le port par défaut, vous pouvez omettre ces paramètres.

Définition d'un document

Pour configurer notre objet document, nous devons définir les données que nous voulons que notre objet document ait. À l'instar de nombreux autres ORM, nous allons le faire en sous-classant le Document classe et en fournissant les types de données que nous voulons:

importer datetime

classer Poster(Document):
    Titre = StringField(obligatoire=Vrai, longueur maximale=200)
    teneur = StringField(obligatoire=Vrai)
    auteur = StringField(obligatoire=Vrai, longueur maximale=50)
    publié = DateTimeField(défaut=datetime.datetime.à présent)

REMARQUE: L'une des tâches les plus difficiles avec les modèles de base de données est la validation des données. Comment vous assurez-vous que les données que vous enregistrez sont conformes au format dont vous avez besoin? Tout simplement parce qu'une base de données est censée être sans schéma ne veut pas dire que c'est sans schéma.

Dans ce modèle simple, nous avons dit à MongoEngine que nous nous attendions à un Poster instance d'avoir un Titre, teneur, une auteur, et le Date il a été publié. Maintenant la base Document object peut utiliser ces informations pour valider les données que nous lui fournissons.

Ainsi, par exemple, si nous essayons de sauvegarder un Poster sans un Titre alors il lancera un Exception et laissez-nous savoir. Nous pouvons aller encore plus loin et ajouter plus de restrictions, comme la longueur de la chaîne. Notez que certains champs ont un longueur maximale jeu de paramètres. Cela raconte le Document, comme vous l'avez probablement deviné, pour n'autoriser qu'une longueur de chaîne maximale du nombre de caractères spécifié. Il y a encore quelques paramètres comme celui-ci que nous pouvons définir, notamment:

  • db_field: Indiquez un autre nom de champ
  • obligatoire: Assurez-vous que ce champ est défini
  • défaut: Utiliser la valeur par défaut donnée si aucune autre valeur n'est donnée
  • unique: Assurez-vous qu'aucun autre document de la collection n'a la même valeur pour ce champ
  • les choix: Assurez-vous que la valeur du champ est égale à l'une des valeurs données dans un tableau

Chaque type de champ a son propre ensemble de paramètres, assurez-vous donc de consulter la documentation pour plus d'informations.

Enregistrer des documents

Pour enregistrer un document dans notre base de données, nous utiliserons le sauvegarder() méthode. Si le document existe déjà dans la base de données, toutes les modifications seront apportées au niveau atomique au document existant. S'il n’existe pas, il sera créé.

Voici un exemple de création et d'enregistrement d'un document:

post_1 = Poster(
    Titre=«Exemple d'article»,
    teneur="Du contenu attrayant",
    auteur=«Scott»
)
post_1.sauvegarder()       # Ceci effectuera une insertion
impression(post_1.Titre)
post_1.Titre = 'Un meilleur titre de message'
post_1.sauvegarder()       # Ceci effectuera une modification atomique sur "titre"
impression(post_1.Titre)

Quelques points à noter sur le .sauvegarder() appeler:

  • PyMongo effectuera la validation lorsque vous appelez .sauvegarder(). Cela signifie qu'il vérifiera les données que vous enregistrez par rapport au schéma que vous avez déclaré dans la classe. Si le schéma (ou une contrainte) est violé, une exception est levée et les données ne sont pas enregistrées.
  • Étant donné que Mongo ne prend pas en charge les vraies transactions, il n'y a aucun moyen de «revenir en arrière» .sauvegarder() appelez comme vous pouvez dans les bases de données SQL. Bien que vous puissiez vous rapprocher de l'exécution de transactions avec des validations en deux phases, elles ne prennent toujours pas en charge les annulations.

Que se passe-t-il lorsque vous laissez le Titre?

post_2 = Poster(teneur=«Le contenu va ici», auteur='Michael')
post_2.sauvegarder()

Vous devriez voir l'exception suivante:

augmenter Erreur de validation(un message, les erreurs=les erreurs)
mongoengine.les erreurs.Erreur de validation:
Erreur de validation (Poster:Aucun) (Domaine est obligatoire: [[[['Titre'])

Fonctions orientées objet

Avec MongoEngine étant orienté objet, vous pouvez également ajouter des méthodes à votre document sous-classé. Prenons l'exemple suivant où une fonction est utilisée pour modifier le jeu de requêtes par défaut (qui renvoie tous les objets de la collection). En utilisant ceci, nous pouvons appliquer un filtre par défaut à la classe et obtenir uniquement les objets souhaités:

classer Poster(Document):
    Titre = StringField()
    publié = BooleanField()

    @queryset_manager
    def live_posts(clazz, jeu de requêtes):
        revenir jeu de requêtes.filtre(publié=Vrai)

Référence à d'autres documents

Vous pouvez également utiliser le ReferenceField objet pour créer une référence d'un document à un autre. MongoEngine gère automatiquement le dé-référencement paresseux lors de l'accès, ce qui est plus robuste et moins sujet aux erreurs que de devoir se souvenir de le faire vous-même partout dans votre code. Un exemple:

classer Auteur(Document):
    Nom = StringField()

classer Poster(Document):
    auteur = ReferenceField(Auteur)

Poster.objets.première().auteur.Nom

Dans le code ci-dessus, en utilisant une référence de document, nous pouvons facilement trouver l'auteur du premier article.

Il y a beaucoup plus de classes de champs (et de paramètres) que ce que nous avons présenté ici, alors assurez-vous de consulter la documentation sur les champs pour plus d'informations.

À partir de tous ces exemples, vous devriez être en mesure de voir que MongoEngine est bien adapté pour gérer vos objets de base de données pour à peu près n'importe quel type d'application. Les fonctionnalités disponibles à la disposition du développeur rendent incroyablement facile la création d'un programme efficace et évolutif. Si vous recherchez une aide supplémentaire sur MongoEngine, assurez-vous de consulter leur guide d'utilisation complet.

Conclusion

Python étant un langage moderne de haut niveau, hautement évolutif, il a besoin d'une base de données (et d'un pilote) capable de maintenir son potentiel, c'est pourquoi MongoDB convient si bien.

Nous avons vu dans cet article comment nous pouvons exploiter les atouts de MongoDB à notre avantage et créer une application hautement flexible et évolutive. N'hésitez pas à nous faire part de vos réflexions dans la section commentaires!

Il s'agit d'une collaboration entre Scott Robinson, auteur de Stack Abuse et les gens de Real Python.

[ad_2]