1. TypeScript Express tutorial #1. Middleware, routing, and controllers 2. TypeScript Express tutorial #2. MongoDB, models and environment variables 3. TypeScript Express tutorial #3. Error handling and validating incoming data 4. TypeScript Express tutorial #4. Registering users and authenticating with JWT 5. TypeScript Express tutorial #5. MongoDB relationships between documents

Today we dive into MongoDB relationships between documents. To do it we use Mongoose and the populate feature. As always, the code that we cover here is available in the express-typescript repository. You’re welcome to give it a star.

MongoDB relationships between documents

The fact is that MongoDB is a NoSQL database. It means that it is non-relational, among other things. To implement a kind of relations between documents, we use references by IDsor embed documents directly.

In the previous part of the tutorial , we saved a reference to the author of the post as authorId. Let’s look into how can we handle that using features of Mongoose like the populate function. To start, we explain relationships in a traditional meaning with examples of implementing them using MongoDB and Mongoose .

One-To-One (1:1)

We can use it to describe MongoDB relationships between two entities where the element of type A may be linked to just one element of type B and vice versa. Imagine having an address schema:

import * as mongoose from 'mongoose'; const addressSchema = new mongoose.Schema({ city: String, street: String, });

In our application there is a big chance that just one user is living at a particular address, meaning a combination of a street and a city. Therefore, it makes sense to relate a specific object of address to just one user, and the user to just one address. User-address is a decent example of a One-To-One relationship, and because of that, we can use the fastest way of creating MongoDB relationships: embedding documents .

import * as mongoose from 'mongoose'; import User from './user.interface'; const addressSchema = new mongoose.Schema({ city: String, street: String, }); const userSchema = new mongoose.Schema({ address: addressSchema, email: String, name: String, password: String, }); const userModel = mongoose.model<User & mongoose.Document>('User', userSchema); export default userModel;
TypeScript Express tutorial #5. MongoDB relationships between documents

The address object got created along with the user and had been given a distinct ID. We can go to the mLab interface and look it up. There, you can see that it is embedded straight into the user document.


TypeScript Express tutorial #5. MongoDB relationships between documents

The One-To-One relationship in this example means that a user has just one address and this address belongs to only one user. Since this is the case, it makes sense to embed the address straight into the user document.

One-To-Many (1:N)

One-To-Many can be used to describe MongoDB relationships in which one side can have more than one relationship with the other, while the reverse relationship can only be one-sided. Let’s implement it in our application with blog posts and authors, assuming that a blog post can just have one author. It is a One-To-Many relationship because a user can be the author of many blog posts, but a blog post can only have one author. We could embed the blog post into the author document, but it would be difficult to maintain. A better idea is to refer to a user inside the post document.

import * as mongoose from 'mongoose'; import Post from './post.interface'; const postSchema = new mongoose.Schema({ author: { ref: 'User', type: mongoose.Schema.Types.ObjectId, }, content: String, title: String, }); const postModel = mongoose.model<Post & mongoose.Document>('Post', postSchema); export default postModel;

The ref : 'User' refers to the “User” document because we named it like that here:

mongoose.model<User & mongoose.Document>('User', userSchema);

Thanks to defining such a reference, now you can assign the user id to the author property of a post.

private createPost = async (request: RequestWithUser, response: express.Response) => { const postData: CreatePostDto = request.body; const createdPost = new this.post({ ...postData, author: request.user._id, }); const savedPost = await createdPost.save(); response.send(savedPost); }
TypeScript Express tutorial #5. MongoDB relationships between documents
Populating the data with Mongoose

A great thing about it is that you can very easily replace the id with the actual data of an author with the populate function that Mongoose implements.

private createPost = async (request: RequestWithUser, response: express.Response) => { const postData: CreatePostDto = request.body; const createdPost = new this.post({ ...postData, author: request.user._id, }); const savedPost = await createdPost.save(); await savedPost.populate('author').execPopulate(); response.send(savedPost); }

Small issue with that is the fact that it also returns the password hash of the user. Fortunately, the populate function accepts additional options.

The first option is to choose the properties that you want to select:

populate('author', 'name')

In the example above only the name of the author and his id is attached. The second way is to exclude the properties that you want to omit:

populate('author', '-password')
TypeScript Express tutorial #5. MongoDB relationships between documents

You can do the same thing in other parts of the application, for example when fetching all the posts:

private getAllPosts = async (request: express.Request, response: express.Response) => { const posts = await this.post.find() .populate('author', '-password'); response.send(posts); } An important thing to notice here is the difference between savedPost . populate ( 'author' ) . execPopulate ( ) and this . post . find ( ) . populate ( 'author' , '-password' ) . In the first example, we call populate on an instance of a Document . To execute it, we need to call

本文数据库(综合)相关术语:系统安全软件

代码区博客精选文章
分页:12
转载请注明
本文标题:TypeScript Express tutorial #5. MongoDB relationships between documents
本站链接:https://www.codesec.net/view/627827.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(194)