Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()

Integre o MongoDB às funções do Vercel para a experiência sem servidor

Nic Raboy7 min read • Published Jun 28, 2022 • Updated Sep 09, 2024
Facebook Icontwitter iconlinkedin icon
Avaliar este tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Trabalha com o Functions as a Service (FaaS), geralmente chamado de serverless, mas você está preso quando se trata de tentar fazer seu banco de dados funcionar? Dada a natureza dessas funções sem servidor, interagir com um banco de dados é uma experiência um pouco diferente do que se você fosse criar seu próprio back-end totalmente hospedado.
Por que é uma experiência diferente, embora?
Os bancos de dados em geral, não apenas o MongoDB, podem ter uma quantidade finita de conexões simultâneas. Quando você hospeda seu próprio aplicativo da web, esse aplicativo normalmente se conecta ao seu banco de dados uma vez e enquanto o aplicativo estiver em execução, o mesmo acontece com a conexão com o banco de dados. No entanto, as funções oferecem uma experiência diferente. Em vez de um aplicativo sempre disponível, agora você está trabalhando com um aplicativo que pode ou não estar disponível no momento da solicitação para economizar recursos. Se você tentar se conectar ao seu banco de dados em sua lógica de função, correrá o risco de muitas conexões. Se a função desligar, hibernar ou semelhante, você correrá o risco de que sua conexão com o banco de dados não esteja mais disponível.
In this tutorial, we're going to see how to use the MongoDB Node.js driver with Vercel functions, something quite common when developing Next.js applications.

Os requisitos

Há alguns requisitos que devem ser atendidos antes de começar a usar este tutorial, dependendo de até onde você deseja ir.
  • Você deve ter um MongoDB Atlas cluster implantado, camada grátis (M0) ou melhor.
  • You should have a Vercel account if you want to deploy to production.
  • Uma versão recente do Node.js e NPM deve estar disponível.
In this tutorial, we're not going to deploy to production. Everything we plan to do can be tested locally, but if you want to deploy, you'll need a Vercel account and either the CLI installed and configured or your Git host. Both are out of the scope of this tutorial.
While we'll get into the finer details of MongoDB Atlas later in this tutorial, you should already have a MongoDB Atlas account and a cluster deployed. If you need help with either, consider checking out this tutorial.
A grande coisa que você precisará é o Node.js. Nós o usaremos para desenvolver e testar nosso aplicativo Next.js.

Criando um novo aplicativo Next.js com a CLI

Criar um novo projeto Next.js é fácil quando se trabalha com a CLI. Em uma linha de comando, supondo que o Node.js esteja instalado, execute o seguinte comando:
1npx create-next-app@latest
You'll be prompted for some information which will result in your project being created. At any point in this tutorial, you can execute npm run dev to build and serve your application locally. You'll be able to test your Vercel functions too!
Antes de prosseguirmos, vamos adicionar a dependência do driver MongoDB Node.js:
1yarn add mongodb
We won't explore it in this tutorial, but Vercel offers a starter template with the MongoDB Atlas integration already configured. If you'd like to learn more, check out the tutorial by Jesse Hall: Como conectar o MongoDB Atlas ao Vercel usando a nova integração. Instead, we'll look at doing things manually to get an idea of what's happening at each stage of the development cycle.

Configurando um cluster de banco de dados no MongoDB Atlas

Neste ponto, você já deve ter uma conta do MongoDB Atlas com um projeto e cluster criados. O nível gratuito é adequado para este tutorial.
Em vez de usar nossa mente para criar um novo conjunto de dados para esse exemplo, vamos usar um dos bancos de dados de amostra disponíveis para os usuários do MongoDB.
Load a MongoDB Sample Dataset
Carregar um conjunto de dados de amostra do MongoDB
No painel do MongoDB Atlas, clique no menu de reticências de um dos clusters e, em seguida, escolha carregar os conjuntos de dados de amostra. Pode levar alguns minutos, então dê algum tempo.
For this tutorial, we're going to make use of the sample_restaurants database, but in reality, it doesn't really matter as the focus of this tutorial is around setup and configuration rather than the actual data.
With the sample dataset loaded, go ahead and create a new user in the "Database Access" tab of the dashboard followed by adding your IP address to the "Network Access" rules. You'll need to do this in order to connect to MongoDB Atlas from your Next.js application. If you choose to deploy your application, you'll need to add a 0.0.0.0 rule as per the Vercel documentation.

Conecte-se ao MongoDB e conexões de cache para uma experiência otimizada para desempenho

Next.js é uma dessas tecnologias em que existem algumas maneiras de resolver o problema. Poderemos interagir com o MongoDB no tempo de construção, criando um site 100% gerado estático, mas há muitos motivos pelos quais podemos querer manter as coisas adhoc em uma função sem servidor.
Within your Next.js project, create a .env.local file with the following variables:
1NEXT_ATLAS_URI=YOUR_ATLAS_URI_HERE
2NEXT_ATLAS_DATABASE=sample_restaurants
3NEXT_ATLAS_COLLECTION=restaurants
Remember, we're using the sample_restaurants database in this example, but you can be adventurous and use whatever you'd like. Don't forget to swap the connection information in the .env.local file with your own.
Next, create a lib/mongodb.js file within your project. This is where we'll handle the actual connection steps. Populate the file with the following code:
1import { MongoClient } from "mongodb";
2
3const uri = process.env.NEXT_ATLAS_URI;
4const options = {
5 useUnifiedTopology: true,
6 useNewUrlParser: true,
7};
8
9let mongoClient = null;
10let database = null;
11
12if (!process.env.NEXT_ATLAS_URI) {
13 throw new Error('Please add your Mongo URI to .env.local')
14}
15
16export async function connectToDatabase() {
17 try {
18 if (mongoClient && database) {
19 return { mongoClient, database };
20 }
21 if (process.env.NODE_ENV === "development") {
22 if (!global._mongoClient) {
23 mongoClient = await (new MongoClient(uri, options)).connect();
24 global._mongoClient = mongoClient;
25 } else {
26 mongoClient = global._mongoClient;
27 }
28 } else {
29 mongoClient = await (new MongoClient(uri, options)).connect();
30 }
31 database = await mongoClient.db(process.env.NEXT_ATLAS_DATABASE);
32 return { mongoClient, database };
33 } catch (e) {
34 console.error(e);
35 }
36}
It might not look like much, but quite a bit of important things are happening in the above file, specific to Next.js and serverless functions. Specifically, take a look at the connectToDatabase function:
1export async function connectToDatabase() {
2 try {
3 if (mongoClient && database) {
4 return { mongoClient, database };
5 }
6 if (process.env.NODE_ENV === "development") {
7 if (!global._mongoClient) {
8 mongoClient = await (new MongoClient(uri, options)).connect();
9 global._mongoClient = mongoClient;
10 } else {
11 mongoClient = global._mongoClient;
12 }
13 } else {
14 mongoClient = await (new MongoClient(uri, options)).connect();
15 }
16 database = await mongoClient.db(process.env.NEXT_ATLAS_DATABASE);
17 return { mongoClient, database };
18 } catch (e) {
19 console.error(e);
20 }
21}
O objetivo da função acima é fornecer-nos uma conexão de cliente para trabalhar, bem como um banco de dados. No entanto, os detalhes mais refinados sugerem que só precisamos estabelecer uma nova conexão se não existir uma e não enviar spam para nosso banco de dados com conexões se estivermos no modo de desenvolvimento para Next.js. O servidor de desenvolvimento local se comporta de forma diferente da que você teria na produção, por isso a necessidade de verificar.
Lembre-se, as quantidades de conexão são finitas e só devemos nos conectar se ainda não estivermos conectados.
Então, o que estamos fazendo na função é que primeiro verificamos se essa conexão existe. Em caso afirmativo, retorne-o e permita que o que estiver chamando a função use essa conexão. Se a conexão não existir e estivermos no modo de desenvolvimento, verificamos se temos uma sessão em cache e a usamos, se tivermos. Caso contrário, precisamos criar uma conexão e armazená-la em cache para o modo de desenvolvimento ou produção.
Se você entender alguma coisa do código acima, entenda que estamos apenas criando conexões se as conexões ainda não existirem.

Executando queries do MongoDB a partir de uma função do Vercel no aplicativo Next.js

We've done the difficult part already. We have a connection management system in place for MongoDB to be used throughout our Vercel application. The next part involves creating API endpoints, in a near identical way to Express Framework, and consuming them from within the Next.js front end.
Então, com o que isso se parece exatamente?
Within your project, create a pages/api/list.js file with the following JavaScript code:
1import { connectToDatabase } from "../../lib/mongodb";
2
3export default async function handler(request, response) {
4
5 const { database } = await connectToDatabase();
6 const collection = database.collection(process.env.NEXT_ATLAS_COLLECTION);
7
8 const results = await collection.find({})
9 .project({
10 "grades": 0,
11 "borough": 0,
12 "restaurant_id": 0
13 })
14 .limit(10).toArray();
15
16 response.status(200).json(results);
17
18}
Vercel functions exist within the pages/api directory. In this case, we're building a function with the goal of listing out data. Specifically, we're going to list out restaurant data.
In our code above, we are leveraging the connectToDatabase function from our connection management code. When we execute the function, we're getting a connection without worrying whether we need to create one or reuse one. The underlying function code handles that for us.
Com uma conexão, podemos encontrar todos os documentos dentro de uma coleção. Nem todos os campos são importantes para nós, então estamos usando uma projeção para excluir o que não queremos. Em vez de retornar todos os documentos dessa grande coleção, estamos limitando os resultados a apenas alguns.
Os resultados são retornados para qualquer código ou cliente externo que os solicite.
If we wanted to consume the endpoint from within the Next.js application, we might do something like the following in the pages/index.js file:
1import { useEffect, useState } from "react";
2import Head from 'next/head'
3import Image from 'next/image'
4import styles from '../styles/Home.module.css'
5
6export default function Home() {
7
8 const [restaurants, setRestaurants] = useState([]);
9
10 useEffect(() => {
11 (async () => {
12 const results = await fetch("/api/list").then(response => response.json());
13 setRestaurants(results);
14 })();
15 }, []);
16
17 return (
18 <div className={styles.container}>
19 <Head>
20 <title>Create Next App</title>
21 <meta name="description" content="Generated by create next app" />
22 <link rel="icon" href="/favicon.ico" />
23 </Head>
24
25 <main className={styles.main}>
26 <h1 className={styles.title}>
27 MongoDB with <a href="https://nextjs.org">Next.js!</a> Example
28 </h1>
29 <br />
30 <div className={styles.grid}>
31 {restaurants.map(restaurant => (
32 <div className={styles.card} key={restaurant._id}>
33 <h2>{restaurant.name}</h2>
34 <p>{restaurant.address.street}</p>
35 </div>
36 ))}
37 </div>
38 </main>
39 </div>
40 )
41}
Ignoring the boilerplate Next.js code, we added a useState and useEffect like the following:
1const [restaurants, setRestaurants] = useState([]);
2
3useEffect(() => {
4 (async () => {
5 const results = await fetch("/api/list").then(response => response.json());
6 setRestaurants(results);
7 })();
8}, []);
O código acima consumirá a API quando o componente carregar. Podemos então renderizá-lo na seção a seguir:
1<div className={styles.grid}>
2 {restaurants.map(restaurant => (
3 <div className={styles.card} key={restaurant._id}>
4 <h2>{restaurant.name}</h2>
5 <p>{restaurant.address.street}</p>
6 </div>
7 ))}
8</div>
Não há nada fora do comum acontecendo no processo de consumo ou renderização. O trabalho pesado que era importante estava na própria função, bem como em nosso arquivo de gerenciamento de conexões.

Conclusão

Você acabou de ver como usar o MongoDB Atlas com funções do Vercel, que é uma solução sem servidor que exige um tipo de abordagem diferente. Lembre-se, ao lidar com serverless, a disponibilidade de suas funções está no ar. Você não quer gerar muitas conexões e não quer tentar usar conexões que não existem. Resolvemos isso armazenando nossas conexões em cache e usando a conexão em cache, se disponível. Caso contrário, crie uma nova conexão.
Got a question or think you can improve upon this solution? Share it in the MongoDB Community Forums!

Facebook Icontwitter iconlinkedin icon
Avaliar este tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Início rápido

How to Use MongoDB Transactions in Node.js


Aug 24, 2023 | 10 min read
Início rápido

Criando AI multiagentes de IA com BuildSship e MongoDB


Nov 18, 2024 | 3 min read
Tutorial

Adicione memória ao seu aplicativo JavaScript RAG usando MongoDB e LangChain


Sep 18, 2024 | 9 min read
Tutorial

Combinando seu banco de dados com o Azure Blob Storage usando o Data Federation


Oct 08, 2024 | 7 min read