Mappage de bases de données relationnelles et SQL sur MongoDB

NoSQL les bases de données ont énormément émergé ces dernières années en raison de leur structure moins contraignante, de leur conception de schéma évolutive et de leur accès plus rapide par rapport aux bases de données relationnelles traditionnelles (SGBDR / SQL). MongoDB est une base de données NoSQL open source orientée document qui stocke des données sous la forme d'objets de type JSON. Elle est devenue l'une des principales bases de données en raison de son schéma dynamique, de sa grande évolutivité, de ses performances de requête optimales, de son indexation plus rapide et de sa communauté d'utilisateurs active..

Si vous venez d’un environnement RDBMS / SQL, la compréhension des concepts NoSQL et MongoDB peut être un peu difficile au début car les deux technologies ont une manière très différente de représenter les données. Cet article vous aidera à comprendre comment le domaine SGBDR / SQL, ses fonctionnalités, ses termes et son langage de requête sont mappés sur la base de données MongoDB. Par mappage, je veux dire que si nous avons un concept dans SGBDR / SQL, nous verrons quel est son concept équivalent dans MongoDB..

Nous allons commencer par mapper les concepts relationnels de base tels que table, ligne, colonne, etc., puis nous aborderons l’indexation et les jointures. Nous examinerons ensuite les requêtes SQL et discuterons des requêtes correspondantes de la base de données MongoDB. L'article suppose que vous connaissez les concepts de base des bases de données relationnelles et SQL, car il sera davantage mis l'accent sur la compréhension de la correspondance entre ces concepts et MongoDB. Commençons.


Mappage de tables, de lignes et de colonnes

Chaque base de données dans MongoDB est constituée de collections équivalentes à une base de données SGBDR composée de tables SQL. Chaque collection stocke des données sous la forme de documents, ce qui équivaut à des tables stockant des données en lignes. Lorsqu'une ligne stocke des données dans son ensemble de colonnes, un document a une structure de type JSON (appelée BSON dans MongoDB). Enfin, dans la manière dont nous avons des lignes dans une ligne SQL, nous avons des champs dans MongoDB. Voici un exemple de document (ligne de lecture) comportant des champs (colonnes de lecture) stockant des données utilisateur:

"_id": ObjectId ("5146bb52d8524270060001f3"), "age": 25 ans, "ville": "Los Angeles", "email": "[email protected]", "nom_utilisateur": "Mark Hanks"

Ce document équivaut à une seule ligne dans le SGBDR. Une collection est composée de nombreux documents, tout comme une table est composée de plusieurs lignes. Notez que chaque document dans une collection a un unique _id champ, qui est un champ de 12 octets qui sert de clé primaire pour les documents. Le champ est généré automatiquement à la création du document et est utilisé pour identifier chaque document de manière unique..

Pour mieux comprendre les mappages, prenons un exemple de table SQL utilisateurs et sa structure correspondante dans MongoDB. Comme le montre la figure 1, chaque ligne de la table SQL se transforme en document et chaque colonne en champ dans MongoDB..


Figure 1

Schéma dynamique

Une chose intéressante à souligner ici est que différents documents dans une collection peuvent avoir différents schémas. Ainsi, dans MongoDB, un document peut comporter cinq champs et l’autre document, sept. Les champs peuvent être facilement ajoutés, supprimés et modifiés à tout moment. En outre, il n'y a aucune contrainte sur les types de données des champs. Ainsi, à un moment donné, un champ peut contenir int type de données et à la prochaine instance, il peut contenir un tableau.

Ces concepts doivent sembler très différents pour les lecteurs issus du SGBDR où les structures de table, leurs colonnes, les types de données et les relations sont prédéfinis. Cette fonctionnalité permettant d'utiliser un schéma dynamique nous permet de générer des documents dynamiques au moment de l'exécution..

Par exemple, considérons les deux documents suivants dans la même collection mais ayant des schémas différents (Fig 2):


Figure 2

Le premier document contient les champs adresse et dob qui ne sont pas présents dans le deuxième document alors que le deuxième contient des champs le sexe et Occupation qui ne sont pas présents dans le premier. Imaginez si nous avions conçu cette chose en SQL, nous aurions gardé quatre colonnes supplémentaires pour adresse, dob, le sexe et Occupation, dont certaines stockent des valeurs vides (ou nulles) et occupent donc un espace inutile.

Ce modèle de schéma dynamique est la raison pour laquelle les bases de données NosSQL sont très évolutives en termes de conception. Différents schémas complexes (hiérarchiques, arborescents, etc.) qui nécessiteraient un nombre de tables de SGBDR peuvent être conçus efficacement à l'aide de tels documents. Un exemple typique serait de stocker les publications des utilisateurs, leurs goûts, commentaires et autres informations associées sous la forme de documents. Une implémentation SQL identique devrait idéalement avoir des tables séparées pour stocker les publications, les commentaires et les préférences, alors qu'un document MongoDB peut stocker toutes ces informations dans un seul document..


Cartographie des jointures et des relations

Les relations dans le SGBDR sont réalisées à l'aide de relations de clé primaire et étrangère et d'interrogation de celles utilisant des jointures. Il n’existe pas de mappage aussi simple dans MongoDB, mais les relations sont conçues ici à l’aide de documents incorporés et de liens..

Prenons un exemple dans lequel nous devons stocker des informations utilisateur et des informations de contact correspondantes. Une conception SQL idéale aurait deux tables, disons informations de l'utilisateur et Informations de contact, avec des clés primaires identifiant et contact_id comme le montre la Fig 3. Le Informations de contact la table contiendrait aussi une colonne identifiant d'utilisateur qui serait la clé étrangère reliant à la identifiant domaine de la informations de l'utilisateur table.


figure 3

Nous allons maintenant voir comment nous pourrions concevoir de telles relations dans MongoDB en utilisant des approches de liaison de documents et de documents incorporés. Notez que dans le schéma SQL, nous ajoutons généralement une colonne (comme identifiant et contact_id dans notre cas) qui agit comme une colonne primaire pour cette table. Cependant, dans MongoDB, nous utilisons généralement la génération automatique _id champ comme clé primaire pour identifier de manière unique les documents.

Lier des documents

Cette approche utilisera deux collections, informations de l'utilisateur et Informations de contact les deux ayant leur unique _id des champs. Nous aurons un champ identifiant d'utilisateur dans le Informations de contact document relatif à la _id domaine de la informations de l'utilisateur document indiquant à quel utilisateur correspond le contact. (Voir Fig 4) Notez que dans MongoDB, les relations et leurs opérations correspondantes doivent être gérées manuellement (par exemple, via le code) car aucune contrainte ni règle de clé étrangère ne s'applique..


Figure 4

le identifiant d'utilisateur champ dans notre document est simplement un champ qui contient des données et toute la logique qui y est associée doit être implémentée par nous. Par exemple, même si vous allez insérer des identifiant d'utilisateur dans le Informations de contact document qui n'existe pas dans le informations de l'utilisateur collection, MongoDB ne va pas lancer d'erreur en disant que correspondant identifiant d'utilisateur n'a pas été trouvé dans le informations de l'utilisateur collection (contrairement à SQL où il s'agirait d'une contrainte de clé étrangère non valide).

Incorporation de documents

La deuxième approche consiste à intégrer le Informations de contact document à l'intérieur du informations de l'utilisateur document comme celui-ci (Fig 5):


Figure 5

Dans l'exemple ci-dessus, nous avons intégré un petit document d'informations de contact dans les informations utilisateur. De la même manière, des documents complexes volumineux et des données hiérarchiques peuvent être incorporés comme ceci pour relier des entités.

En outre, quelle approche utiliser entre les approches de liaison et intégrée dépend du scénario spécifique. Si la taille des données à incorporer doit croître, il est préférable d’utiliser l’approche Liaison plutôt que l’approche Embedded pour éviter que le document ne devienne trop volumineux. L'approche intégrée est généralement utilisée dans les cas où une quantité limitée d'informations (telle que l'adresse dans notre exemple) doit être intégrée.


Tableau de cartographie

Pour résumer, le tableau suivant (Fig 6) représente les relations communes que nous avons discutées:


Figure 6

Mappage SQL aux requêtes MongoDB

Maintenant que nous sommes à l'aise avec les mappages de base entre SGBDR et MongoDB, nous verrons en quoi le langage de requête utilisé pour interagir avec la base de données diffère entre eux..

Pour les requêtes MongoDB, supposons une collection utilisateurs avec la structure du document comme suit:

"_id": ObjectId ("5146bb52d8524270060001f3"), "post_text": "Ceci est un exemple de publication", "user_name": "mark", "post_privacy": "public", "post_likes_count": 0

Pour les requêtes SQL, nous supposons que la table utilisateurs ayant cinq colonnes avec la structure suivante:


Figure 7

Nous discuterons des requêtes liées à la création et à la modification de collections (ou de tables), à l'insertion, à la lecture, à la mise à jour et à la suppression de documents (ou de lignes). Il existe deux requêtes pour chaque point, une pour SQL et une autre pour MongoDB. J'expliquerai les requêtes MongoDB uniquement car nous sommes assez familiers avec les requêtes SQL. Les requêtes MongoDB présentées ici sont écrites dans le shell Mongo JavaScript tandis que les requêtes SQL sont écrites dans MySQL.

Créer

Dans MongoDB, il n’est pas nécessaire de créer explicitement la structure de la collection (comme nous le faisons pour les tables utilisant un CREER LA TABLE question). La structure du document est automatiquement créée lors de la première insertion dans la collection. Cependant, vous pouvez créer une collection vide en utilisant createCollection commander.

 SQL: CREATE TABLE 'posts' ('id' int (11) NOT NULL AUTO_INCREMENT, 'post_text' varchar (500) NOT NULL, 'nom_utilisateur' varchar (20) NOT NULL, 'post_privacy' varchar (10) NOT NULL, ' post_likes_count 'int (11) NOT NULL, PRIMARY KEY (' id ')) MongoDB: db.createCollection ("posts")

Insérer

Pour insérer un document dans MongoDB, nous utilisons le insérer méthode qui prend un objet avec des paires clé-valeur en entrée. Le document inséré contiendra le fichier généré automatiquement. _id champ. Cependant, vous pouvez aussi explicitement fournir une valeur de 12 octets en tant que _id avec les autres champs.

 SQL: INSERT INTO 'posts' ('id', 'post_text', 'nom_utilisateur', 'post_privacy', 'post_likes_count') VALEURS (NULL, 'Ceci est un exemple de message', 'marque', 'public', '0 '); MongoDB: db.posts.insert (user_name: "mark", post_text: "Ceci est un exemple de publication", post_privacy: "public", post_likes_count: 0)

Il n'y a pas Alter Table fonction dans MongoDB pour changer la structure du document. Comme les documents sont dynamiques dans le schéma, le schéma change au fur et à mesure des mises à jour du document..

Lis

MongoDB utilise le trouver méthode qui est équivalente à la SÉLECTIONNER commande en SQL. Les déclarations suivantes lisent simplement tous les documents du des postes collection.

 SQL: SELECT * FROM 'posts' MongoDB: db.posts.find ()

La requête suivante effectue une recherche conditionnelle pour les documents ayant Nom d'utilisateur champ comme marque. Tous les critères pour récupérer les documents doivent être placés dans les premières accolades séparées par des virgules.

 SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' MongoDB: db.posts.find (user_name: "mark")

La requête suivante récupère des colonnes spécifiques, post_text  et post_likes_count comme spécifié dans le deuxième ensemble d'accolades .

 SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' MongoDB: db.posts.find (, post_text: 1, post_likes_count: 1)

Notez que MongoDB renvoie par défaut le _id champ avec chaque déclaration find. Si nous ne voulons pas de ce champ dans notre jeu de résultats, nous devons spécifier le _id clé avec un 0 valeur dans la liste des colonnes à récupérer. le 0 la valeur de la clé indique que nous voulons exclure ce champ du jeu de résultats.

 MongoDB: db.posts.find (, post_text: 1, post_likes_count: 1, _id: 0)

La requête suivante extrait des champs spécifiques en fonction des critères Nom d'utilisateur est marque.

 SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' MongoDB: db.posts.find (user_name: "mark", post_text: 1, post_likes_count: 1)

Nous allons maintenant ajouter un critère supplémentaire pour extraire les articles dont le type de confidentialité est public. Les champs de critères spécifiés par des virgules représentent la logique ET état. Ainsi, cette déclaration cherchera des documents ayant à la fois Nom d'utilisateur comme marque et post_privacy comme Publique.

 SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' AND 'post_privacy' = 'public' MongoDB: db.posts.find (user_name: "mark", post_privacy: "public" , post_text: 1, post_likes_count: 1)

Pour utiliser logique OU entre les critères de la trouver méthode, nous utilisons le $ ou opérateur.

 SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' OU 'post_privacy' = 'public' MongoDB: db.posts.find ($ ou: [user_name: "mark" , post_privacy: "public"], post_text: 1, post_likes_count: 1)

Ensuite, nous allons utiliser le Trier méthode qui trie le résultat dans l'ordre croissant de post_likes_count(indiqué par 1).

 SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' commande par post_likes_count ASC MongoDB: db.posts.find (user_name: "mark"). Sort (post_likes_count: 1)

Pour trier les résultats par ordre décroissant, nous spécifions -1 comme valeur du champ.

 SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' commande par post_likes_count DESC MongoDB: db.posts.find (user_name: "mark"). Sort (post_likes_count: -1)

Pour limiter le nombre de documents à retourner, nous utilisons le limite méthode spécifiant le nombre de documents.

 SQL: SELECT * FROM 'posts' LIMIT 10 MongoDB: db.posts.find (). Limit (10)

La façon dont nous utilisons décalage en SQL pour sauter un certain nombre d'enregistrements, nous utilisons sauter fonction dans MongoDB. Par exemple, l’énoncé suivant va chercher dix articles en sautant les cinq premiers.

 SQL: SELECT * FROM 'posts' LIMIT 10 OFFSET 5 MongoDB: db.posts.find (). Limit (10) .skip (5)

Mettre à jour

Le premier paramètre à la mettre à jour méthode spécifie les critères de sélection des documents. Le deuxième paramètre spécifie l'opération de mise à jour à effectuer. Par exemple, la requête suivante sélectionne tous les documents avec Nom d'utilisateur comme marque et définit leur post_privacy comme privé.

Une différence ici est que par défaut, MongoDB mettre à jour query met à jour un seul document (et le premier correspondant). Pour mettre à jour tous les documents correspondants, nous devons fournir un troisième paramètre spécifiant multi comme vrai indiquant que nous voulons mettre à jour plusieurs documents.

SQL: UPDATE posts SET post_privacy = "privé" WHERE nom_utilisateur = "marque" MongoDB: db.posts.update (nom_utilisateur: "marque", $ set: post_privacy: "privé", multi: vrai )

Retirer

La suppression de documents est assez simple et similaire à SQL.

 SQL: DELETE FROM posts WHERE nom_utilisateur = "marque" MongoDB: db.posts.remove (nom_utilisateur: "marque")

Indexage

MongoDB a un index par défaut créé sur le _id champ de chaque collection. Pour créer de nouveaux index sur les champs, nous utilisons assurerIndex méthode spécifiant les champs et l’ordre de tri associé indiqué par 1 ou -1(ascendant ou descendant).

 SQL: CREATE INDEX index_posts ON posts (nom_utilisateur, post_likes_count DESC) MongoDB: db.posts.ensureIndex (utilisateur_nom: 1, post_likes_count: -1)

Pour voir tous les index présents dans n'importe quelle collection, nous utilisons getIndexes méthode sur les mêmes lignes de MONTRER INDEX requête de SQL.

 SQL: SHOW INDEX FROM postes MongoDB: db.posts.getIndexes ()

Conclusion

Dans cet article, nous avons compris la relation entre les concepts et termes élémentaires de SGBDR / SQL dans MongoDB. Nous avons examiné la conception des relations dans MongoDB et avons appris comment mapper les fonctionnalités des requêtes SQL de base dans MongoDB..

Après avoir pris l’avance avec cet article, vous pouvez continuer à essayer des requêtes complexes, notamment l’agrégation, la réduction de mappage et les requêtes impliquant plusieurs collections. Vous pouvez également utiliser l'aide de certains outils en ligne pour convertir les requêtes SQL en requêtes MongoDB au début. Vous pouvez créer vous-même un exemple de schéma de base de données MongoDB. Un des meilleurs exemples serait une base de données pour stocker les publications des utilisateurs, leurs mentions, leurs commentaires et leurs commentaires. Cela vous donnerait une vue pratique de la conception de schéma flexible offerte par MongoDB..

N'hésitez pas à commenter toute suggestion, question ou idée que vous voudriez voir plus loin.