From f9fa592c3df7ec910ccdd278698557be70fc9172 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Mon, 2 May 2022 17:51:42 +0300 Subject: [PATCH 1/9] ent hello world example --- en/app-dev-overview.md | 6 ++ en/for-ent.md | 198 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 en/for-ent.md diff --git a/en/app-dev-overview.md b/en/app-dev-overview.md index 6368cd9..95c2fde 100644 --- a/en/app-dev-overview.md +++ b/en/app-dev-overview.md @@ -151,6 +151,12 @@ This document lists some of the app development guides that show you how to buil Verified App Development for GORM + + Ent + v0.10.2 or later + Verified + App Development for Ent + diff --git a/en/for-ent.md b/en/for-ent.md new file mode 100644 index 0000000..d998353 --- /dev/null +++ b/en/for-ent.md @@ -0,0 +1,198 @@ +--- +title: App Development for Ent +summary: Learn how to build a simple Golang application based on TiDB and Ent. +--- + +# App Development for Ent + +This tutorial shows you how to build a simple Golang application based on TiDB and Ent. The sample application to build here is a simple Todo app where you can add, query, and update Todos. + +## Step 1. Start a TiDB cluster + +Start a pseudo TiDB cluster on your local storage: + +{{< copyable "" >}} + +```bash +docker run -p 127.0.0.1:$LOCAL_PORT:4000 pingcap/tidb:v5.4.0 +``` + +The above command starts a temporary and single-node cluster with mock TiKV. The cluster listens on the port `$LOCAL_PORT`. After the cluster is stopped, any changes already made to the database are not persisted. + +> **Note:** +> +> To deploy a "real" TiDB cluster for production, see the following guides: +> +> + [Deploy TiDB using TiUP for On-Premises](https://docs.pingcap.com/tidb/v5.4/production-deployment-using-tiup) +> + [Deploy TiDB on Kubernetes](https://docs.pingcap.com/tidb-in-kubernetes/stable) +> +> You can also [use TiDB Cloud](https://pingcap.com/products/tidbcloud/), a fully-managed Database-as-a-Service (DBaaS), which offers free trial. + +## Step 2. Create a database + +1. In the SQL shell, create the `entgo` database that your application will use: + + {{< copyable "" >}} + + ```sql + CREATE DATABASE entgo; + ``` + +2. Create a SQL user for your application: + + {{< copyable "" >}} + + ```sql + CREATE USER IDENTIFIED BY ; + ``` + + Take note of the username and password. You will use them in your application code when initializing the project. + +3. Grant necessary permissions to the SQL user you have just created: + + {{< copyable "" >}} + + ```sql + GRANT ALL ON entgo.* TO ; + ``` + +## Step 3. Get and run the application code + +### Prerequisites +Make sure you have [Go](https://golang.org/doc/install) installed (1.17 or above). +Create a folder for this demo, and initialize using `go mod`: + +{{< copyable "" >}} + +```bash +mkdir todo +cd todo +go mod init todo +``` +### Initialize project +To initialize the project, run the following commands: + +{{< copyable "" >}} + +```bash +go get -d entgo.io.ent/cmd/ent +``` +First, we need to install Ent and initialize the project structure. run: + +{{< copyable "" >}} + +```bash +go get -d entgo.io/ent/cmd/ent +go run entgo.io/ent/cmd/ent init Todo +``` +After running the above, your project directory should look like this: +```bash +. +├── ent +│ ├── generate.go +│ └── schema +│ └── todo.go +├── go.mod +└── go.sum +``` +Open `schema/todo.go` and add some fields to the `Todo` entity: + +{{< copyable "" >}} + +```go +func (Todo) Fields() []ent.Field { + return []ent.Field{ + field.String("title"), + field.String("content"), + field.Bool("done"). + Default(false), + field.Time("created_at"), + } +} +``` +Finally, run: + +{{< copyable "" >}} + +```bash +go generate ./ent +``` + +### Run the example application +Create a file named `main.go` in your project's root folder and copy to it the the following code: + +{{< copyable "" >}} + +```go +package main + +import ( + "context" + "fmt" + "log" + "time" + "todo/ent" + "todo/ent/todo" + + "entgo.io/ent/dialect/sql/schema" + _ "github.com/go-sql-driver/mysql" +) + +func main() { + // Connect to TiDB. + client, err := ent.Open("mysql", "root@tcp(127.0.0.1:4000)/entgo?parseTime=true") + if err != nil { + log.Fatal("error opening ent client", err) + } + defer client.Close() + // Migrate the local schema with the DB. + if err := client.Schema.Create( + context.Background(), + // TiDB support is possible with Atlas engine only. + schema.WithAtlas(true), + ); err != nil { + log.Fatal("error migrating DB", err) + } + + // Create some todos + client.Todo.Create(). + SetTitle("buy groceries"). + SetContent("tomato, lettuce and cucumber"). + SetCreatedAt(time.Now()). + SaveX(context.Background()) + client.Todo.Create(). + SetTitle("See my doctor"). + SetContent("periodic blood test"). + SetCreatedAt(time.Now()). + SaveX(context.Background()) + + // query todo with 'where' filter + todos := client.Todo.Query(). + Where(todo.ContentContains("tomato")). + AllX(context.Background()) + fmt.Printf("The following todos contain 'tomato' in their content: %v\n", todos) + + // after buying the groceries, set the todo as done. + client.Todo.UpdateOne(todos[0]).SetDone(true).ExecX(context.Background()) + + // delete todos that are done. + deletedCount := client.Todo.Delete().Where(todo.Done(true)).ExecX(context.Background()) + fmt.Printf("deleted %d todos\n", deletedCount) +} +``` +### Run the code + +Run the `main.go` code: + +{{< copyable "" >}} + +```bash +go run main.go +``` + +The expected output is as follows: +``` +The following todos contain 'tomato' in their content: +[Todo(id=11, title=buy groceries, content=tomato, lettuce and cucumber, done=false, created_at=Mon May 2 14:32:20 2022)] +deleted 1 todos +``` From 0ff0c9ea051bb130d9a13d93a29b02743f6b8640 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 3 May 2022 11:13:43 +0300 Subject: [PATCH 2/9] use latest ent version --- en/app-dev-overview.md | 2 +- en/for-ent.md | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/en/app-dev-overview.md b/en/app-dev-overview.md index 95c2fde..ed8b0d0 100644 --- a/en/app-dev-overview.md +++ b/en/app-dev-overview.md @@ -153,7 +153,7 @@ This document lists some of the app development guides that show you how to buil - + diff --git a/en/for-ent.md b/en/for-ent.md index d998353..b0e6b60 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -70,13 +70,6 @@ cd todo go mod init todo ``` ### Initialize project -To initialize the project, run the following commands: - -{{< copyable "" >}} - -```bash -go get -d entgo.io.ent/cmd/ent -``` First, we need to install Ent and initialize the project structure. run: {{< copyable "" >}} @@ -193,6 +186,6 @@ go run main.go The expected output is as follows: ``` The following todos contain 'tomato' in their content: -[Todo(id=11, title=buy groceries, content=tomato, lettuce and cucumber, done=false, created_at=Mon May 2 14:32:20 2022)] +[Todo(id=1, title=buy groceries, content=tomato, lettuce and cucumber, done=false, created_at=Mon May 2 14:32:20 2022)] deleted 1 todos ``` From 6db29dc9c8110557dc0d80e0badcaa248bec72a1 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 3 May 2022 11:15:44 +0300 Subject: [PATCH 3/9] format --- en/for-ent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/for-ent.md b/en/for-ent.md index b0e6b60..eb1a3e1 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -159,7 +159,7 @@ func main() { SetCreatedAt(time.Now()). SaveX(context.Background()) - // query todo with 'where' filter + // query todo with 'where' filter todos := client.Todo.Query(). Where(todo.ContentContains("tomato")). AllX(context.Background()) From 22450764287c75196c3fa2c2b4e223f89ef1472a Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 3 May 2022 11:37:18 +0300 Subject: [PATCH 4/9] Update en/for-ent.md Co-authored-by: MasseElch <12862103+masseelch@users.noreply.github.com> --- en/for-ent.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/en/for-ent.md b/en/for-ent.md index eb1a3e1..d6bc3ab 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -75,8 +75,7 @@ First, we need to install Ent and initialize the project structure. run: {{< copyable "" >}} ```bash -go get -d entgo.io/ent/cmd/ent -go run entgo.io/ent/cmd/ent init Todo +go run -mod=mod entgo.io/ent/cmd/ent init Todo ``` After running the above, your project directory should look like this: ```bash From d14cd70a6b8c7bf1fa9cbf1670bf97f1e7eb2d26 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 3 May 2022 11:37:24 +0300 Subject: [PATCH 5/9] Update en/for-ent.md Co-authored-by: MasseElch <12862103+masseelch@users.noreply.github.com> --- en/for-ent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/for-ent.md b/en/for-ent.md index d6bc3ab..b005557 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -158,7 +158,7 @@ func main() { SetCreatedAt(time.Now()). SaveX(context.Background()) - // query todo with 'where' filter + // query todo with 'where' filter todos := client.Todo.Query(). Where(todo.ContentContains("tomato")). AllX(context.Background()) From 747bf9c4f9d27bfb7b545199220400ea98921ea4 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Sun, 8 May 2022 10:07:00 +0300 Subject: [PATCH 6/9] latest tidb version --- en/for-ent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/en/for-ent.md b/en/for-ent.md index eb1a3e1..90bd722 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -14,7 +14,7 @@ Start a pseudo TiDB cluster on your local storage: {{< copyable "" >}} ```bash -docker run -p 127.0.0.1:$LOCAL_PORT:4000 pingcap/tidb:v5.4.0 +docker run -p 127.0.0.1:$LOCAL_PORT:4000 pingcap/tidb:v6.0.0 ``` The above command starts a temporary and single-node cluster with mock TiKV. The cluster listens on the port `$LOCAL_PORT`. After the cluster is stopped, any changes already made to the database are not persisted. From 7a6661d175d616c0228eab85eeaa6cfc0d52dc13 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 24 May 2022 15:40:58 +0300 Subject: [PATCH 7/9] add external links --- en/for-ent.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/en/for-ent.md b/en/for-ent.md index c17d3b7..4f27cea 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -188,3 +188,12 @@ The following todos contain 'tomato' in their content: [Todo(id=1, title=buy groceries, content=tomato, lettuce and cucumber, done=false, created_at=Mon May 2 14:32:20 2022)] deleted 1 todos ``` + +## What's next? + +Learn more about how to use [Ent Framework](https://entgo.io/). + +You might also be interested in the following: +* Automatically generate feature-rich, performant, and clean [GraphQL](https://entgo.io/docs/graphql/), [REST](https://entgo.io/blog/2021/07/29/generate-a-fully-working-go-crud-http-api-with-ent/), and [gRPC](https://entgo.io/docs/grpc-intro/) servers using Ent +* [Versioned Migrations with Ent](https://entgo.io/docs/versioned-migrations/) +* [Extending Ent with the Extension API](https://entgo.io/blog/2021/09/02/ent-extension-api) From a985edf4fa6791a4183b5db052ec88f44febf723 Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 24 May 2022 15:48:52 +0300 Subject: [PATCH 8/9] fenced code blocks --- en/for-ent.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/en/for-ent.md b/en/for-ent.md index 4f27cea..14f51af 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -69,6 +69,7 @@ mkdir todo cd todo go mod init todo ``` + ### Initialize project First, we need to install Ent and initialize the project structure. run: @@ -77,6 +78,7 @@ First, we need to install Ent and initialize the project structure. run: ```bash go run -mod=mod entgo.io/ent/cmd/ent init Todo ``` + After running the above, your project directory should look like this: ```bash . @@ -87,6 +89,7 @@ After running the above, your project directory should look like this: ├── go.mod └── go.sum ``` + Open `schema/todo.go` and add some fields to the `Todo` entity: {{< copyable "" >}} @@ -102,6 +105,7 @@ func (Todo) Fields() []ent.Field { } } ``` + Finally, run: {{< copyable "" >}} @@ -172,6 +176,7 @@ func main() { fmt.Printf("deleted %d todos\n", deletedCount) } ``` + ### Run the code Run the `main.go` code: @@ -183,6 +188,7 @@ go run main.go ``` The expected output is as follows: + ``` The following todos contain 'tomato' in their content: [Todo(id=1, title=buy groceries, content=tomato, lettuce and cucumber, done=false, created_at=Mon May 2 14:32:20 2022)] From bb5f05886914a6e1e2cc7141c87e1cd0fd5cc1ca Mon Sep 17 00:00:00 2001 From: Amit Shani Date: Tue, 24 May 2022 15:55:40 +0300 Subject: [PATCH 9/9] fix markdownlint --- en/for-ent.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/en/for-ent.md b/en/for-ent.md index 14f51af..767d99b 100644 --- a/en/for-ent.md +++ b/en/for-ent.md @@ -59,6 +59,7 @@ The above command starts a temporary and single-node cluster with mock TiKV. The ## Step 3. Get and run the application code ### Prerequisites + Make sure you have [Go](https://golang.org/doc/install) installed (1.17 or above). Create a folder for this demo, and initialize using `go mod`: @@ -71,6 +72,7 @@ go mod init todo ``` ### Initialize project + First, we need to install Ent and initialize the project structure. run: {{< copyable "" >}} @@ -80,6 +82,7 @@ go run -mod=mod entgo.io/ent/cmd/ent init Todo ``` After running the above, your project directory should look like this: + ```bash . ├── ent @@ -115,6 +118,7 @@ go generate ./ent ``` ### Run the example application + Create a file named `main.go` in your project's root folder and copy to it the the following code: {{< copyable "" >}} @@ -200,6 +204,7 @@ deleted 1 todos Learn more about how to use [Ent Framework](https://entgo.io/). You might also be interested in the following: + * Automatically generate feature-rich, performant, and clean [GraphQL](https://entgo.io/docs/graphql/), [REST](https://entgo.io/blog/2021/07/29/generate-a-fully-working-go-crud-http-api-with-ent/), and [gRPC](https://entgo.io/docs/grpc-intro/) servers using Ent * [Versioned Migrations with Ent](https://entgo.io/docs/versioned-migrations/) * [Extending Ent with the Extension API](https://entgo.io/blog/2021/09/02/ent-extension-api)
Entv0.10.2 or later Verified App Development for Ent