diff --git a/content/02-understand-prisma/03-prisma-in-your-stack/03-is-prisma-an-orm.mdx b/content/02-understand-prisma/03-prisma-in-your-stack/03-is-prisma-an-orm.mdx index 889e7e2864..fac7829788 100644 --- a/content/02-understand-prisma/03-prisma-in-your-stack/03-is-prisma-an-orm.mdx +++ b/content/02-understand-prisma/03-prisma-in-your-stack/03-is-prisma-an-orm.mdx @@ -10,7 +10,7 @@ To answer the question briefly: _No, Prisma is not an ORM_. The main goal of Prisma is to make working with databases easier for application developers. In that sense, it shares the same goals with ORMs, but takes a fundamentally different approach. -ORMs are libraries that map tables in your database to classes in your programming language. Prisma on the other hand is an auto-generated query builder that exposes queries which are _tailored_ to your models. All Prisma Client queries return plain old JavaScript objects. +ORMs are libraries that map tables in your database to classes in your programming language. Prisma, on the other hand, is a database toolkit. The toolkit includes Prisma Client, which is an auto-generated query builder that exposes queries which are _tailored_ to your models. All Prisma Client queries return plain old JavaScript objects. To understand how Prisma and ORMs differ conceptually, here's a brief overview of how their building blocks relate to databases: diff --git a/content/02-understand-prisma/06-api-comparisons/01-prisma-and-mongoose.mdx b/content/02-understand-prisma/06-api-comparisons/01-prisma-and-mongoose.mdx new file mode 100644 index 0000000000..f2c1fdd2bb --- /dev/null +++ b/content/02-understand-prisma/06-api-comparisons/01-prisma-and-mongoose.mdx @@ -0,0 +1,286 @@ +--- +title: 'Comparing Prisma and Mongoose' +metaTitle: 'Comparing Prisma and Mongoose' +metaDescription: 'Compare the Prisma and Mongoose APIs.' +--- + +## Overview + +This page compares the Prisma and [Mongoose](https://mongoosejs.com/docs/guide.html) APIs. + + +## Fetching single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, +}); +``` +**Mongoose** + +```ts +const result = await User.findById("5eb9354624286a04e42401d8"); +``` + +## Fetching selected scalars of single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, + select: { + name: true, + }, +}); +``` + +**Mongoose** + +```ts +const user = await User.findById("5eb9354624286a04e42401d8").select([ + "name", + "email", +]); +``` + +## Fetching relations + +**Prisma** + + +```ts +const posts = await prisma.user.findOne({ + where: { + id: 2, + }, + include: { + post: true, + }, +}); +``` + +```ts +const posts = await prisma.user + .findOne({ + where: { + id: 2, + }, + }) + .post(); +``` + + + +**Mongoose** + +```ts +const userWithPosts = await User + .findById(id) + .populate("posts") +``` + +## Filtering for concrete values + +**Prisma** + +```ts +const posts = await prisma.post.findMany({ + where: { + title: { + contains: "Hello World", + }, + }, +}); +``` + + +**Mongoose** + +```ts +const user = await Post.find({ + title: "Hello World" +}) +``` + +## Other filter criteria + +**Prisma** + +Prisma generates many [additional filters](../../reference/tools-and-interfaces/prisma-client/filtering) that are commonly used in modern application development. + +**Mongoose** + +Mongoose exposes the [MongoDB query selectors](https://docs.mongodb.com/manual/reference/operator/query/#query-selectors) as filter criteria. + +## Relation filters + +**Prisma** + +Prisma lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. + +For example, the following query returns users with one or more posts with "Hello" in the title: + +```ts +const posts = await prisma.user.findMany({ + where: { + Post: { + some: { + title: { + contains: "Hello", + }, + }, + }, + } +}); +``` + +**Mongoose** + +Mongoose doesn't offer a dedicated API for relation filters. You can get similar functionality by adding an additional step to filter the results returned by the query. + +## Pagination + +**Prisma** + +Cursor-style pagination: + +```ts +const page = prisma.post.findMany({ + before: { + id: 242, + }, + last: 20, +}); +``` + +Offset pagination: + +```ts +const cc = prisma.post.findMany({ + skip: 200, + first: 20, +}); +``` + +**Mongoose** + +```ts +const posts = await Post.find({ + skip: 5, + limit: 10 +}) +``` + +## Creating objects + +**Prisma** + +```ts +const user = await prisma.user.create({ + data: { + email: "alice@prisma.io", + }, +}); +``` +**Mongoose** + + + +```ts +const user = await User.create({ + name: "Alice", + email: "alice@prisma.io" +}) +``` + +```ts +const user = new User({ + name: "Alice", + email: "alice@prisma.io" +}) +await user.save() +``` + + + +## Updating objects + +**Prisma** + +```ts +const user = await prisma.user.update({ + data: { + name: "Alicia", + }, + where: { + id: 2 + } +}); +``` +**Mongoose** + + + +```ts +const updatedUser = await User.findOneAndUpdate( + { _id: id }, + { + $set: { + name: "James", + email: "james@prisma.io" + } + } +) +``` + +```ts +user.name = "James" +user.email =" james@prisma.com" +await user.save() +``` + + + +## Deleting objects + +**Prisma** + +```ts +const user = prisma.user.delete({ + where: { + id: 10, + }, +}); +``` +**Mongoose** + +```ts +await User.deleteOne({ _id: id }) +``` + +## Batch deletes + +**Prisma** + +```ts +const users = await prisma.user.deleteMany({ + where: { + id: { + in: [1, 2, 6, 6, 22, 21, 25], + }, + }, +}); +``` + +**Mongoose** + +```ts +await User.deleteMany({ userUID: uid, id: { $in: [10, 2, 3, 5]}}) +``` \ No newline at end of file diff --git a/content/02-understand-prisma/06-api-comparisons/02-prisma-and-sequelize.mdx b/content/02-understand-prisma/06-api-comparisons/02-prisma-and-sequelize.mdx new file mode 100644 index 0000000000..4cbe04b951 --- /dev/null +++ b/content/02-understand-prisma/06-api-comparisons/02-prisma-and-sequelize.mdx @@ -0,0 +1,396 @@ +--- +title: 'Comparing Prisma and Sequelize' +metaTitle: 'Comparing Prisma and Sequelize' +metaDescription: 'Compare the Prisma and Sequelize APIs.' +--- + +## Overview + +This page compares the Prisma and [Sequelize](http://docs.sequelizejs.com/) APIs. + +## Fetching single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, +}); +``` + +**Sequelize** + +```ts +const user = await User.findByPk(id) +``` + +## Fetching selected scalars of single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, + select: { + name: true, + }, +}); +``` + +**Sequelize** + +```ts +const user = await User.findByPk(1, { attributes: ["name"], raw: true }); +``` + +> **Tip** Use the `raw: true` query option to return plain Javascript objects. + +## Fetching relations + +**Prisma** + + + +```ts +const posts = await prisma.user.findOne({ + where: { + id: 2, + }, + include: { + post: true, + }, +}); +``` + +```ts +const posts = await prisma.user.findOne({ + where: { + id: 2, + }, +}) +.post(); +``` + + + +> **Note**: `select` return a `user` object that includes a `post` array, whereas the fluent API only returns a `post` array. + +**Sequelize** + +```ts +const user = await User.findByPk(id, { + include: [{ + model: Post + }] +}) +``` + +> **Tip**: Use `model: Post as "Post"` if you used an alias to define the relationship between `User` and `Post` - for example: `User.hasMany(Post, { as: "Post", foreignKey: "authorId" });` + +## Filtering for concrete values + +**Prisma** + +```ts +const posts = await prisma.post.findMany({ + where: { + title: { + contains: "Hello", + }, + }, +}); +``` + +**Sequelize** + +```ts +const post = await Post.findAll({ + raw: true, + where: { + title: { + [Op.like]: "%Hello%", + }, + }, +}); +``` + +## Other filter criteria + +**Prisma** + +Prisma generates many [additional filters](../../reference/tools-and-interfaces/prisma-client/filtering) that are commonly used in modern application development. + +**Sequelize** + +Sequelize has an [extensive set of operators](http://docs.sequelizejs.com/manual/tutorial/querying.html#operators). + +## Relation filters + +**Prisma** + +Prisma lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. + +For example, the following query returns users with one or more posts with "Hello" in the title: + +```ts +const posts = await prisma.user.findMany({ + where: { + Post: { + some: { + title: { + contains: "Hello", + }, + }, + }, + } +}); +``` + +**Sequelize** + +Sequelize [doesn't offer a dedicated API for relation filters](https://github.com/sequelize/sequelize/issues/10943). You can get similar functionality by sending a raw SQL query to the database. + +## Pagination + +**Prisma** + +Cursor-style pagination: + +```ts +const page = prisma.post.findMany({ + before: { + id: 242, + }, + last: 20, +}); +``` + +Offset pagination: + +```ts +const cc = prisma.post.findMany({ + skip: 200, + first: 20, +}); +``` + +**Sequelize** + +```ts +const posts = await Post.findAll({ + offset: 5, + limit: 10 +}) +``` + +## Creating objects + +**Prisma** + +```ts +const user = await prisma.user.create({ + data: { + email: "alice@prisma.io", + }, +}); +``` + +**Sequelize** + + + +```ts +const user = User.build({ + name: "Alice", + email: "alice@prisma,io" +}) +await user.save() +``` + +```ts +const user = await User.create({ + name: "Alice", + email: "alice@prisma,io" +}) +``` + + + +## Updating objects + +**Prisma** + +```ts +const user = await prisma.user.update({ + data: { + name: "Alicia", + }, + where: { + id: 2 + } +}); +``` + +**Sequelize** + + + +```ts +user.name = "James" +user.email =" alice@prisma.com" +await user.save() +``` + +```ts +await User.update({ + name: "James", + email: "james@prisma.io" +}) +``` + + + +## Deleting objects + +**Prisma** + +```ts +const user = prisma.user.delete({ + where: { + id: 10, + }, +}); +``` + +**Sequelize** + +```ts +await user.destroy() +``` + +## Batch updates + +**Prisma** + +```ts +const user = await prisma.user.updateMany({ + data: { + name: "Published author!", + }, + where: { + email: { + contains: "prisma.io" + } + }, +}); +``` + +**Sequelize** + +```ts +const updatedUsers = await User.update({ + { role: "Admin" }, + where: { + email: { + [Op.like]: "%@prisma.io" + } + }, +}) +``` + +## Batch deletes + +**Prisma** + +```ts +const users = await prisma.user.deleteMany({ + where: { + id: { + in: [1, 2, 6, 6, 22, 21, 25], + }, + }, +}); +``` + +**Sequelize** + +```ts +await User.destroy({ + where: { + id: { + [Op.in]: [id1, id2, id3] + } + } +}) +``` + +## Transactions + +**Prisma** + +```ts +const user = await prisma.user.create({ + data: { + email: "bob.rufus@prisma.io", + name: "Bob Rufus", + Post: { + create: [ + { title: "Working at Prisma" }, + { title: "All about databases" }, + ], + }, + }, +}); +``` + +**Sequelize** + + + +```ts +return sequelize.transaction(async t => { + const user = await User.create({ + name: "Alice", + email: "alice@prisma,io" + }, { + transaction: t + }) + const post1 = await Post.create({ + title: "Join us for GraphQL Conf in 2019" + }, { + transaction: t + }) + const post2 = await Post.create({ + title: "Subscribe to GraphQL Weekly for GraphQL news" + }, { + transaction: t + }) + await user.setPosts([post1, post2]) +}) +``` + +```ts +return sequelize.transaction(async transaction => { + try { + const user = await User.create({ + name: "Alice", + email: "alice@prisma,io" + }) + const post1 = await Post.create({ + title: "Join us for GraphQL Conf in 2019" + }) + const post2 = await Post.create({ + title: "Subscribe to GraphQL Weekly for GraphQL news" + }) + await user.setPosts([post1, post2]) + } catch(e) { + return t.rollback() + } +}) +``` + + \ No newline at end of file diff --git a/content/02-understand-prisma/06-api-comparisons/03-prisma-and-typeorm.mdx b/content/02-understand-prisma/06-api-comparisons/03-prisma-and-typeorm.mdx new file mode 100644 index 0000000000..ce80af45f4 --- /dev/null +++ b/content/02-understand-prisma/06-api-comparisons/03-prisma-and-typeorm.mdx @@ -0,0 +1,397 @@ +--- +title: 'Comparing Prisma and TypeORM' +metaTitle: 'Comparing Prisma and TypeORM' +metaDescription: 'Compare Prisma and TypeORM.' +--- + +## Overview + +This page compares Prisma and [TypeORM](https://typeorm.io/#/). + +## API comparison + +### Fetching single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, +}); +``` + +**TypeORM** + +```ts +const userRepository = getRepository(User) +const user = await userRepository.findOne(id) +``` + +### Fetching selected scalars of single objects + +**Prisma** + +```ts +const user = await prisma.user.findOne({ + where: { + id: 1, + }, + select: { + name: true, + }, +}); +``` + +**TypeORM** + +```ts +const userRepository = getRepository(User) +const user = await userRepository.findOne(id, { + select: ["id", "email"] +}) +``` + +### Fetching relations + +**Prisma** + + + + +```ts +const posts = await prisma.user.findOne({ + where: { + id: 2, + }, + include: { + post: true, + }, +}); +``` + +```ts +const posts = await prisma.user.findOne({ + where: { + id: 2, + }, +}) +.post(); +``` + + + +> **Note**: `select` return a `user` object that includes a `post` array, whereas the fluent API only returns a `post` array. + +**TypeORM** + + + +```ts +const userRepository = getRepository(User) +const user = await userRepository.findOne(id, { + relations: ["posts"] +}) +``` + +```ts +const userRepository = getRepository(User) +const user = await userRepository.findOne(id, { + join: { + alias: "user", + leftJoinAndSelect: { + posts: "user.posts" + } + } +}) +``` + +```ts +const userRepository = getRepository(User) +const user = await userRepository.findOne(id) +``` + + + +### Filtering for concrete values + +**Prisma** + +```ts +const posts = await prisma.post.findMany({ + where: { + title: { + contains: "Hello", + }, + }, +}); +``` + +**TypeORM** + +```ts +const userRepository = getRepository(User) +const users = await userRepository.find({ + where: { + name: "Alice" + } +}) +``` + +### Other filter criteria + +**Prisma** + +Prisma generates many [additional filters](../../reference/tools-and-interfaces/prisma-client/filtering) that are commonly used in modern application development. + +**TypeORM** + +TypeORM provides [built-in operators](https://typeorm.io/#/find-options/advanced-options) that can be used to create more complex comparisons + +### Relation filters + +**Prisma** + +Prisma lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. + +For example, the following query returns users with one or more posts with "Hello" in the title: + +```ts +const posts = await prisma.user.findMany({ + where: { + Post: { + some: { + title: { + contains: "Hello", + }, + }, + }, + } +}); +``` + +**TypeORM** + +TypeORM doesn't offer a dedicated API for relation filters. You can get similar functionality by using the `QueryBuilder` or writing the queries by hand. + +### Pagination + +**Prisma** + +Cursor-style pagination: + +```ts +const page = prisma.post.findMany({ + before: { + id: 242, + }, + last: 20, + }); +``` +Offset pagination: + +```ts +const cc = prisma.post.findMany({ + skip: 200, + first: 20, +}); +``` + +**TypeORM** + +```ts +const postRepository = getRepository(Post) +const posts = await postRepository.find({ + skip: 5, + take: 10 +}) +``` + +### Creating objects + +**Prisma** + +```ts +const user = await prisma.user.create({ + data: { + email: "alice@prisma.io", + }, +}); +``` + +**TypeORM** + + + +```ts +const user = new User() +user.name = "Alice" +user.email = "alice@prisma.io" +await user.save() +``` + +```ts +const userRepository = getRepository(User) +const user = await userRepository.create({ + name: "Alice", + email: "alice@prisma.io" +}) +await user.save() +``` + +```ts +const userRepository = getRepository(User) +await userRepository.insert({ + name: "Alice", + email: "alice@prisma.io" +}) +``` + + + +### Updating objects + +**Prisma** + +```ts +const user = await prisma.user.update({ + data: { + name: "Alicia", + }, + where: { + id: 2 + } +}); +``` + +**TypeORM** + +```ts +const userRepository = getRepository(User) +const updatedUser = await userRepository.update(id, { + name: "James", + email: "james@prisma.io" +}) +``` + +### Deleting objects + +**Prisma** + +```ts +const user = prisma.user.delete({ + where: { + id: 10, + }, +}); +``` + +**TypeORM** + + + +```ts +const userRepository = getRepository(User) +await userRepository.delete(id) +``` + +```ts +const userRepository = getRepository(User) +const deletedUser = await userRepository.remove(user) +``` + + + +### Batch updates + +**Prisma** + +```ts +const user = await prisma.user.updateMany({ + data: { + name: "Published author!", + }, + where: { + Post: { + some: { + published: true, + }, + }, + }, +}); +``` + +**TypeORM** + +You can use the [query builder to update entities in your database](https://typeorm.io/#/update-query-builder). + +### Batch deletes + +**Prisma** + +```ts +const users = await prisma.user.deleteMany({ + where: { + id: { + in: [1, 2, 6, 6, 22, 21, 25], + }, + }, +}); +``` + +**TypeORM** + + + +```ts +const userRepository = getRepository(User) +await userRepository.delete([id1, id2, id3]) +``` + +```ts +const userRepository = getRepository(User) +const deleteUsers = await userRepository + .remove([user1, user2, user3]) +``` + + + +### Transactions + +**Prisma** + +```ts +const user = await prisma.user.create({ + data: { + email: "bob.rufus@prisma.io", + name: "Bob Rufus", + Post: { + create: [ + { title: "Working at Prisma" }, + { title: "All about databases" }, + ], + }, + }, +}); +``` + +**TypeORM** + +```ts +await getConnection().transaction(async transactionalEntityManager => { + const user = getRepository(User).create({ + name: "Bob", + email: "bob@prisma.io" + }) + const post1 = getRepository(Post).create({ + title: "Join us for GraphQL Conf in 2019", + }) + const post2 = getRepository(Post).create({ + title: "Subscribe to GraphQL Weekly for GraphQL news", + }) + user.posts = [post1, post2] + await transactionalEntityManager.save(post1) + await transactionalEntityManager.save(post2) + await transactionalEntityManager.save(user) + }) \ No newline at end of file diff --git a/content/02-understand-prisma/06-api-comparisons/index.mdx b/content/02-understand-prisma/06-api-comparisons/index.mdx new file mode 100644 index 0000000000..ff3f3ff3e0 --- /dev/null +++ b/content/02-understand-prisma/06-api-comparisons/index.mdx @@ -0,0 +1,15 @@ +--- +title: 'API comparisons' +metaTitle: 'API comparisons' +metaDescription: 'Comparing Prisma to ORMs and ODMs.' +--- + +## Overview + +Find out how Prisma compares to ORMs and ODMs. + +> Prisma is a **database toolkit** that includes an auto-generated query builder named Prisma Client. Find out [why Prisma is not an ORM](../../prisma-in-your-stack/is-prisma-an-orm). + +## In this section + + diff --git a/content/02-understand-prisma/index.mdx b/content/02-understand-prisma/index.mdx index 07f1e93074..9d421b646f 100644 --- a/content/02-understand-prisma/index.mdx +++ b/content/02-understand-prisma/index.mdx @@ -7,7 +7,7 @@ toc: false ## Overview -Get to know Prisma toolkit and how it fits into your stack. +Get to know the Prisma database toolkit and how it fits into your stack. ## In this section