使用Tigris数据库并使用TRPC和Next.js搜索 - 第1部分
#typescript #nextjs #database #trpc

随着我们继续使用DatabaseSearch等数据服务构建open source Developer Data Platform,我们将不断探索生态系统及其技术,以确定我们的平台解决最大的问题,并且是最适合的问题。

tRPCNext.js在无服务器生态系统中出色。 TRPC的使命是使开发人员能够快速移动,而通过端到端类型API却无所作为,与我们的Tigris数据思考完全一致。特别是,Tigris数据库如何使开发人员能够在Typescript中定义其数据模型,并在其应用程序逻辑(客户端和服务器上)使用它们。

因此,在此教程系列中,我们将使用Tigris数据库,Tigris Search,TRPC和Next.js。

Tigris Database + tRPC + Next.js logos

Tigris是一个生产级平台,旨在处理大型数据集和大量的读写和写入。因此,我们将在许多不同用户中使用10,000个帖子的合理样本量预先加载应用程序。我们将构建列出帖子的功能,并允许您通过它们分页。我们还将添加能够查看特定用户的所有帖子并在所有帖子上执行全文搜索的能力。

这是该应用程序的概述视频,我们将在这三个教程中构建:

该系列分解如下:

  1. 该技术的概述,获取基本的tigris,trpc和next.js应用程序启动和运行,使用Typescript定义模式,并使用Tigris数据库执行简单的读取查询。
  2. 插入邮政文档,添加分页并使用输入和过滤的tigris数据库查询查询查询
  3. 使用tigris搜索与分页添加全文搜索

我们不会构建注册或登录功能,我们也不会过多地专注于我们将使用MUI的UI。

在下一节中,我们将介绍TRPC和Tigris的一些背景(我们假设Next.js不需要简介)。但是,请随时进入下面的三部分教程系列的第一部分。或直接直接进入github上的完整Tigris Database and Search + tRPC + Next.js repo

Backownd

什么是trpc?

tRPC代表打字稿远程过程调用 ,是一个库,可以在客户端和服务器之间启用typesafe远程过程调用。使用TRPC,您可以在服务器上定义一个过程,该过程可以通过客户端代码调用。多亏了TypeScript,您可以确定您正在调用定义的方法并传递强烈键入的参数。您也可以使用开发工具在客户端和服务器上进行重构代码。

如果这仍然不是超清晰的,请不用担心!我们将从教程中的一个非常简单的示例开始。

- 您也可能已经听说了代表远程方法调用的RMI一词。

什么是tigris?

Tigris是open-source Developer Data Platform。我们还提供了名为Tigris Cloud的平台的托管和托管版本,提供了无服务器数据库和无服务器搜索数据服务。

术语开发人员数据平台是合理的。它指的是一个平台,该平台公开了一组数据服务,例如数据库,搜索,消息排队,缓存和客户端/服务器pub/sub作为单个平台,这意味着您不需要管理和同步多个单独的服务。如果您选择使用开发人员数据平台的托管版本(例如Tigris Cloud),那么您将获得所有可爱的无服务器好处,让他人管理这些服务。

Tutorial

在本教程中,您将学习如何:

  • 创建一个Tigris项目并配置Next.js应用程序使用Tigris
  • 使用Typescript定义底格里斯数据库架构
  • 使用trpc useQuery从客户端进行远程过程调用
  • collection.findOnecollection.findMany查询在Tigris数据库中的集合

在您成为Be之前

要遵循本教程,您将需要:

获取code

从github克隆本地代码,导航到新目录,然后切换到bootstrap分支:

git clone https://github.com/tigrisdata-community/tigris-trpc-nextjs.git
cd tigris-trpc-nextjs
git checkout bootstrap

接下来,安装应用依赖项:

npm install

最后,运行该应用程序:

npm run dev

如果您在浏览器中前往[http://localhost:3000](http://localhost:3000),您会看到以下内容:

basic-trpc-app.png

我们将重点关注此代码库中的以下领域:

  1. src/pages-下一个页面。JS应用程序
  2. src/pages/api/trpc/[trpc].ts-我们在哪里定义了从客户端调用的TRPC远程过程。在这里,我们还将使用Tigris TypeScript SDK添加数据驱动功能。
  3. src/components-这里已经定义了一些现有的组件,但是我们会在使用时添加一个新组件。
  4. scripts/-这里已经有几个辅助脚本了。我们还将添加一个脚本来设置我们的Tigris数据库模式。
  5. db/models-该目录尚不存在,但是我们很快就会在其中创建一些Tigris TypeScript data models

创建一个tigris项目并配置下一个。JSApp

运行以下命令来创建一个.env.development.local,并在应用程序中使用tigris所需的变量。

cp .env.development.local.example .env.development.local

打开.env.development.local文件,您将看到以下内容:

TIGRIS_URI=api.preview.tigrisdata.cloud
TIGRIS_PROJECT=tigris_trpc_nextjs
TIGRIS_CLIENT_ID=
TIGRIS_CLIENT_SECRET=
TIGRIS_DB_BRANCH=develop

这种配置假定我们将使用Tigris Cloud(TIGRIS_URI),该项目将被称为tigris_trpc_nextjsâ(TIGRIS_PROJECT),我们将在database branch上工作,称为developTIGRIS_DB_BRANCH)。我们仍然需要填充TIGRIS_CLIENT_IDTIGRIS_CLIENT_SECRET。因此,让我们在Tigris Cloud中创建一个项目。

如果您还没有这样做,signup for a free Tigris Cloud account

然后,在Tigris Web控制台内创建一个新项目。如上所述,假设该项目将被命名为tigris_trpc_nextjs - 因此,如果您决定调用项目其他内容,请确保您更新.env.development.local文件中的值。您会在应用程序键下找到TIGRIS_CLIENT_IDTIGRIS_CLIENT_SECRET的值。

有了底格里斯的配置,我们可以继续定义tigris数据库模式。

首先定义tigris数据库Schema

使用Tigris,您可以使用代码来定义数据库架构,您也可以在应用程序逻辑中使用这些代码。我们认为,这种代码优先的方法是您的模式定义在应用程序的代码库中使用的,并使用与您的其他代码库相同的语言和语法编写,这比必须学习另一种语言来定义数据更强大模型和模式。我们也认为这很酷!

因此,我们的应用程序将有两个数据模型:

  1. Post:用户在应用程序中发布的消息
  2. User:使用该应用程序并发布消息的人的模型表示

让我们从安装tigris thexcript SDK开始:

npm install @tigrisdata/core

接下来,在新文件中定义User模型,src/db/models/user.ts

import {
  Field,
  PrimaryKey,
  TigrisCollection,
  TigrisDataTypes,
} from "@tigrisdata/core";

@TigrisCollection("users")
class User {
  @PrimaryKey(TigrisDataTypes.INT64, { order: 1, autoGenerate: true })
  id?: string;

  @Field()
  username!: string;

  @Field({ timestamp: "createdAt" })
  createdAt?: Date;
}

export default User;

上述代码:

  1. 定义了一个名为User的新类。 User有一个装饰器@TigrisCollection("users"),用于指导Tigris SDK,该集合称为“用户”将包含具有此类定义的结构的文档。

    ðâ€您可以在官方打字稿文档中了解有关TypeScript decorators的更多信息。

  2. id是集合中的主要键,由@PrimaryKey装饰器指示。在该装饰器中,我们还设置了类型(TigrisDataTypes.INT64)并通过{ autoGenerate: true, order: 1 }的其他选项,告诉Tigris这是一个自动生成的字段,这就是为什么我们将其标记为可选的?(注意:order仅使用order如果有多个主键,所以我们可以在这里忽略它)。您可能会注意到,尽管在数据库中是INT64,在打字稿中,我们将id定义为类型string

  3. username属性装饰有Field()。我们不需要在此装饰器中设置类型 - 尽管我们可以 - 因为Typescript SDK通过反射将属性类型视为string。这是应用程序中用户的显示名称,应在创建User并因此用!标记为nonnull时设置。

  4. 最后,有一个createdAt字段。 @Field({ timestamp: "createdAt" })告知Tigris这是一个日期字段,应在创建时用时间戳自动填充(注意:updateAt是另一种选择)。由于该字段在创建时填充了,因此用?标记为可选。

我们还需要一个模型来存储帖子。使用以下代码创建一个src/db/models/post.ts文件:

import {
  Field,
  PrimaryKey,
  TigrisCollection,
  TigrisDataTypes,
} from "@tigrisdata/core";

@TigrisCollection("posts")
class Post {
  @PrimaryKey(TigrisDataTypes.INT64, { order: 1, autoGenerate: true })
  id?: string;

  @Field()
  username!: string;

  @Field()
  text!: string;

  @Field({ timestamp: "createdAt" })
  createdAt?: Date;
}

export default Post;

Post遵循与User相同的原理:

  1. 我们使用@TigrisCollection装饰器来定义一个名为“帖子”的Post
  2. username用于存储张贴人的用户名,而不是无效
  3. text帖子的文字内容,是非零件
  4. User一样,有一个createdAt字段可以指示何时创建帖子。

使用模型,我们需要在scripts/setup.ts中编写一个小脚本来设置Tigris中的数据库模式:

import { Tigris } from "@tigrisdata/core";
import Post from "../src/db/models/post";
import User from "../src/db/models/user";

import { loadEnvConfig } from "@next/env";
loadEnvConfig(process.cwd(), process.env.NODE_ENV !== "production");

async function main(): Promise<void> {
  const tigrisClient = new Tigris();

  // ensure branch exists, create it if it needs to be created dynamically
  await tigrisClient.getDatabase().initializeBranch();
  // register schemas
  await tigrisClient.registerSchemas([User, Post]);
}

main()
  .then(async () => {
    console.log("Setup complete ...");
    process.exit(0);
  })
  .catch(async (e) => {
    console.error(e);
    process.exit(1);
  });

在此脚本中,我们:

  1. 导入Tigris Client和我们刚创建的模型,最后,使用@next/env loadEnvConfig辅助功能加载环境变量。 loadEnvConfig的第二个参数指示是否应加载开发环境变量。当我们运行此脚本时,process.env.NODE_ENV将不会等于生产,因此true将通过,并且我们的.env.development.local的内容将加载。
  2. main函数中,我们创建了Tigris客户端的新实例,该实例从.env.development.local加载环境变量。
  3. await tigrisClient.getDatabase().initializeBranch()确保创建和初始化了带有develop值的名称的分支。
  4. await tigrisClient.registerSchemas([User, Post])将我们刚刚定义并已导入到脚本中的两个数据模型通知Tigris。这将分别创建两个集合,分别是usersposts,并在我们的模型中定义了模式。

更新package.json以具有以下内容的setup脚本:

"scripts": {
    "preadd-users": "npm run setup",
    "add-users": "ts-node ./scripts/add-users.ts",
    "preload-mock-data": "npm run setup",
    "load-mock-data": "ts-node ./scripts/load-mock-data.ts",
    "setup": "ts-node ./scripts/setup.ts",
    "predev": "npm run setup",
    "dev": "next dev",
    "build": "next build",
    "lint": "eslint --ext \".js,.ts,.tsx\" --report-unused-disable-directives src",
    "start": "next start"
},

这添加了两个脚本:

  1. setup-要运行新的setup.ts脚本,我们刚刚创建
  2. predev-运行dev之前运行setup

您会注意到其他几个依赖此新的setup脚本的脚本。这是因为我们的脚本确保了我们的模型和底格里式的同步。

现在,运行:

npm run setup

您将看到输出如下:

$ npm run setup

> tigris-trpc-nextjs@0.1.0 setup
> ts-node ./scripts/setup.ts

info - Using reflection to infer type of Post#username
info - Using reflection to infer type of Post#text
info - Using reflection to infer type of Post#createdAt
info - Using reflection to infer type of User#username
info - Using reflection to infer type of User#createdAt
Loaded env from /Users/leggetter/tmp/tigris-trpc-nextjs/.env.development.local
info - Using Tigris at: api.preview.tigrisdata.cloud:443
event - Created database branch: 'develop'
info - Using database branch: 'develop'
event - Creating collection: 'users' in project: 'tigris_trpc_nextjs'
event - Creating collection: 'posts' in project: 'tigris_trpc_nextjs'
Setup complete ...

从输出中,您可以看到各个字段及其类型是通过反射发现的,环境变量已加载,develop数据库分支,并且在tigris_trpc_nextjs项目中创建了两个集合usersposts

如果您在Tigris Web控制台中前往项目,请从顶部的下拉列表中选择开发分支,您将看到收藏馆现在已定义。

Tigris Database in Tigris Cloud Web Console showing the database schema

添加模拟data

使用数据库架构,让我们添加一些模拟数据,因此我们有一些数据可以在下一个.js应用程序中显示。

您可能已经注意到scripts/add-users.ts脚本和"add-users"脚本在package.json中。这可以通过以下以下方式用于与某些示例用户填充users集合:

npm add-users -- {username1} {username2} ... {usernameX}

所以,继续添加一些用户。如果您没有很有创造力,请随时使用以下内容,这将在Tigris上增加五个团队:

npm run add-users -- leggetter ovaistariq adilansari GarrenSmith HimankChaudhary

所讨论的,运行add-users将首先运行setup,然后运行add-users.ts脚本。输出将如下:

> tigris-trpc-nextjs@0.1.0 add-users
> ts-node ./scripts/add-users.ts leggetter ovaistariq adilansari GarrenSmith HimankChaudhary

info - Using reflection to infer type of User#username
info - Using reflection to infer type of User#createdAt
Loaded env from /Users/leggetter/tmp/tigris-trpc-nextjs/.env.development.local
info - Using Tigris at: api.preview.tigrisdata.cloud:443
Inserting users with usernames: leggetter, ovaistariq, adilansari, GarrenSmith, HimankChaudhary
Users inserted.

不用担心,我们将在本教程系列的稍后进行文档插入代码。

接下来,让我们在posts系列中添加10,000个模拟帖子。我们可以通过package.json中的脚本load-mock-datascripts/load-mock-data.ts中的脚本进行此操作。这使用了mock-data目录中的JSON文件中存储的假数据,并将每个帖子随机归因于我们刚刚插入的一个用户。

ðâ€在创建此应用程序和教程期间,我们发现了一种方便的服务,可帮助您生成模拟数据。

运行load-mock-data脚本:

npm run load-mock-data

运行此操作的输出将查看以下内容:

> tigris-trpc-nextjs@0.1.0 load-mock-data
> ts-node ./scripts/load-mock-data.ts

info - Using reflection to infer type of Post#username
info - Using reflection to infer type of Post#text
info - Using reflection to infer type of Post#createdAt
info - Using reflection to infer type of User#username
info - Using reflection to infer type of User#createdAt
Loaded env from /Users/leggetter/tmp/tigris-trpc-nextjs/.env.development.local
info - Using Tigris at: api.preview.tigrisdata.cloud:443
Gettings users from Users collection
Reading mock file 1 of 10
Reading mock file 2 of 10
Reading mock file 3 of 10
Reading mock file 4 of 10
Reading mock file 5 of 10
Reading mock file 6 of 10
Reading mock file 7 of 10
Reading mock file 8 of 10
Reading mock file 9 of 10
Reading mock file 10 of 10
Loading data complete ...

,您现在将在Tigris数据库中同时拥有用户和模拟帖子。您可以在Tigris Web控制台中前往您的项目,然后选择 Data Explorer 查看数据(请记住要确保您正在查看开发分支。

Tigris Database Tigris Cloud Data Explorer in the Web Console showing Users listed in a table

现在我们有一些数据可以在我们的应用程序中播放,我们可以移至下一个。JS代码库。

通过trpc usequery和tigris数据库query获取用户

在我们开始之前,值得知道使用trpc/examples-next-minimal-starter repo引导代码库。有关该存储库结构的更多详细信息,请参见tRPC Next.js docs,但请忽略有关Prisma的部分。

,我们确实可以潜入代码库。我们要做的第一件事是从users系列中获取用户并采用其身份。这是因为我们没有涵盖本教程中的注册和登录。但是,这也使我们有机会覆盖一个简单的tRPC useQuery

代码已经到位,可以进行远程过程调用以获取静态定义的用户。在src/pages/index.tsx中,您将看到以下内容:

import React from "react";
import { Typography } from "@mui/material";
import { Layout } from "~/components/layout";
import { Loading } from "~/components/loading";

import { trpc } from "../utils/trpc";

export default function IndexPage(): JSX.Element {
  const userPayload = trpc.getUser.useQuery();

  if (userPayload.data === undefined) {
    return <Loading />;
  }

  const user = userPayload.data as { username: string };

  return (
    <Layout username={user.username}>
      <Typography variant="h4" component="h2" mb={5}>
        Welcome, {user.username}
      </Typography>
    </Layout>
  );
}

const userPayload = trpc.getUser.useQuery();行呼叫了一个名为getUser的程序,在src/pages/api/trpc/[trpc].ts中定义了:

import * as trpcNext from "@trpc/server/adapters/next";
import { publicProcedure, router } from "~/server/trpc";
import { z } from "zod";
import CONFIG from "~/config";

const appRouter = router({
  getUser: publicProcedure.query(() => {
    return { username: "staticUser" };
  }),
});

// export only the type definition of the API
// None of the actual implementation is exposed to the client
export type AppRouter = typeof appRouter;

// export API handler
export default trpcNext.createNextApiHandler({
  router: appRouter,
  createContext: () => ({}),
});

现在,getUser过程返回一个内联对象。让我们对此进行更新,以返回Tigris数据库中用户集合中发现的第一个用户:

...

import CONFIG from "~/config";

import { Tigris } from "@tigrisdata/core";
import User from '~/db/models/user';

const tigrisClient = new Tigris();

const appRouter = router({
  getUser: publicProcedure
    .query(async () => {
      const usersCollection = tigrisClient.getDatabase().getCollection<User>(User);
      const user = await usersCollection.findOne();
      return user;
    }),
});

...

让用户:

  1. 我们导入Tigris客户端和User模型
  2. 创建tigris客户端的新实例。
  3. 然后,我们更新getUser过程为async,并更新了查询以执行以下操作:
    1. const usersCollection = tigrisClient.getDatabase().getCollection<User>(User);获取用户集合
    2. const user = await usersCollection.findOne();找到第一个用户
    3. return user;将用户对象返回客户端

而不是返回{ username: "staticUser" }的内联对象,我们将带有username属性的User,因此我们不会看到任何tesscript错误或必须在客户端上进行任何更改。

非常简单,是的!对应用程序UI的更改并不重要,但它代表了向前迈出的一大步,因为该应用程序现在是数据库驱动的。

The social streams app showing a username retrieved from the Tigris Database

从Tigris数据库中检索帖子,并在下一个显示它们。JSApp

早些时候,我们将一堆模拟帖子预加载到Tigris数据库中。让我们更新下一个.js应用程序以检索一些帖子并显示它们。

src/pages/api/trpc/[trpc].js开始,定义一个新的过程,该过程查询posts集合:

...

import { type Cursor, FindQueryOptions, Order, Tigris } from "@tigrisdata/core";
import User from '~/db/models/user';
import Post from '~/db/models/post';

const tigrisClient = new Tigris();
const postsCollection = tigrisClient.getDatabase().getCollection<Post>(Post);

const appRouter = router({
  getUser: publicProcedure
    .query(async () => {
      const usersCollection = tigrisClient.getDatabase().getCollection<User>(User);
      const user = await usersCollection.findOne();
      return user;
    }),

  getMessages: publicProcedure
    .query(async () => {
      const cursor: Cursor<Post> = postsCollection.findMany({
        sort: { field: "createdAt", order: Order.DESC },
        options: new FindQueryOptions(CONFIG.DEFAULT_PAGING_SIZE, 0),
      });

      const results = await cursor.toArray();
      return results;
    }),
});

...

在上述代码中,我们首先导入了一些新的依赖性:

  • FindQueryOptionsOrder-用作posts系列查询的一部分。
  • Cursor-从postCollection.findMany返回的类型
  • Post-由于我们现在正在查询Post文档的集合

我们创建了postCollection变量,以引用我们后来在新的getMessages过程中的查询中使用的posts集合。我们以后也会在其他查询中使用postCollection

在新的getMessages过程中,我们执行以下操作:

  1. postCollection上使用findMany with no filter。默认情况下,这将使集合中的所有文档都能获取,因此我们通过options限制了结果的数量。
  2. 对于options,我们将其传递给FinderQueryOptions对象,其中limit设置为CONFIG.DEFAULT_PAGING_SIZE(该对象设置为20,在src/config.ts中)。第二个参数是skip值,因此我们以0的值传递,因为我们现在没有构建分页(但我们稍后会介绍)。
  3. 我们通过sort属性,并指定蒂格里斯(Tigris)应按降序对createdAt进行排序(Order.DESC)。
  4. 最后,我们将cursor转换为带有await cursor.toArray()的数组,然后将帖子数组返回客户端。

查询新的TRPC程序,并将帖子添加到Ui

使用了新的getMessages过程,我们可以更新src/pages/index.tsx以利用它:

import React, { useEffect, useState } from "react";
import { Typography } from "@mui/material";
import { Layout } from "~/components/layout";
import { Loading } from "~/components/loading";

import { trpc } from "../utils/trpc";
import type Post from "~/db/models/post";
import PostsList from "~/components/posts-list";

export default function IndexPage(): JSX.Element {
  const userPayload = trpc.getUser.useQuery();
  const user = userPayload.data as { username: string };
  const queryPosts = trpc.getMessages.useQuery();

  const [posts, setPosts] = useState<Post[]>([]);

  if (userPayload.data === undefined) {
    return <Loading />;
  }

  useEffect(() => {
    if (queryPosts.status === "success") {
      setPosts(queryPosts.data as Post[]);
    }
  }, [queryPosts.data]);

  return (
    <Layout username={user.username}>
      <Typography variant="h4" component="h2" mb={5}>
        Welcome, {user.username}
      </Typography>

      {queryPosts.status === "loading" && <Loading />}

      {queryPosts.status === "success" && <PostsList posts={posts} />}
    </Layout>
  );
}

首先,导入一些新的依赖项:

  1. useEffectuseState来自React
  2. 我们定义的Post模型的type Post。在服务器上和客户端上使用该模型是帮助避免错误的好方法。
  3. 我们尚未创建的PostList组件。但是我们接下来要这样做。

IndexPage功能中:

  1. const queryPosts = trpc.getMessages.useQuery();呼叫新的getMessages程序。
  2. const [posts, setPosts] = useState<Post[]>([]);存储我们使用该过程检索的帖子,并最终在渲染的UI中使用它们。
  3. 我们将useEffect称为[queryPosts.data](http://queryPosts.data)作为依赖性。这意味着仅在queryPosts.data的值更改时才能运行效果,而这是存储帖子数据的位置。如果查询的statussuccess,那么我们致电setPosts(queryPosts.data as Post[]);设置posts的值。

在UI页的定义中,我们进行了一些更改:

  1. {queryPosts.status === "loading" && <Loading />}渲染<Loading />组件,如果查询状态为loading
  2. {queryPosts.status === "success" && <PostsList posts={posts} />}要渲染尚未完成的<PostsList />组件,如果TRPC查询的状态为success

因此,让我们添加PostsList组件以查看应用程序中的应用程序。创建一个带有以下内容的src/components/posts-list.tsx文件:

import React from "react";
import { Box, Stack, Typography } from "@mui/material";
import PostCard from "~/components/post-card";
import type Post from "~/db/models/post";

export default function PostsList({ posts }: { posts: Post[] }): JSX.Element {
  return (
    <Box id="posts">
      <Stack spacing={2}>
        {posts.length === 0 && <Typography>No posts yet!</Typography>}
        {posts.length > 0 &&
          posts.map((post) => {
            return (
              <PostCard
                key={post.id}
                username={post.username}
                text={post.text}
                createdAt={
                  post.createdAt !== undefined
                    ? new Date(post.createdAt)
                    : new Date()
                }
              />
            );
          })}
      </Stack>
    </Box>
  );
}

<PostsLists />组件的关键点是:

  1. 它采用posts类型Post[]的道具,并将其用于逻辑来确定应该渲染的内容。
  2. 如果posts.length === 0,请显示“尚无帖子!
  3. 否则,通过帖子循环并创建一个新的<PostCard />,通过usernametextcreatedAtPost
  4. createdAt=分配和相关的undefined检查逻辑是由于a bug in the Tigris TypeScript SDK。一旦修复了错误,分配将被简化为createdAt={post.createdAt!},因为这些帖子来自tigris数据库,该数据库是自动填充的,因此我们知道它不会为null。

如果愿意,请查看<PostCard />的源。它使用多个MUI组件。我们也有一些我们没有完全使用的东西,例如像/heart和“共享图标”,但是我们已经留下了这些东西,以使应用程序更加社交,并且是您添加更多功能的机会。

Next.js应用程序现在包含一个用户和Tigris数据库中的帖子,使用TRPC查询检索。

结论

在此Tigris,TRPC和Next.js教程系列的第一部分中,我们介绍了:

  1. 如何使用TypeScript中定义的数据模型定义底格里斯数据库架构,并设置下一个项目。
  2. 如何使用userQuery在Next.js中使用TRPC从客户端到服务器进行远程过程,以及如何查询Tigris数据库并使用TRPC
  3. 将结果返回给客户端
  4. 如何在下一个中渲染TRPC和Tigris数据库查询的结果。JSUI

ð§您可以在github上的part-1 branch中抓取该系列第一部分的完整代码。

在本系列的下一个教程中,我们将通过使用TRPC和inserting a document将数据传递到服务器的数据来显示如何发布消息。我们还将将pagination添加到应用程序中,并在应用程序中添加一个/username页面,该页面将使用Tigris Database filtering

在Twitter上关注@TigrisData和/或我,@leggetter,以确保您不会错过本系列中的下一个教程。您也可以在Mastodon上关注我,并在Twitch上播放类似这样的应用。

我们也希望您加入我们的Tigris Community Discord

,如果您还没有signed up for Tigris,也应该这样做。