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 .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
MongoDBchevron-right

8 Melhores práticas para criar aplicativos FastAPI e MongoDB

Mark Smith8 min read • Published Apr 23, 2024 • Updated Apr 23, 2024
FastAPIMongoDBPython
SNIPPET
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
FastAPI é uma estrutura web moderna e de alto desempenho para construir APIs com Python 3.8 ou posterior, com base em dicas de tipo. Seu design se concentra em codificação rápida e redução de erros, graças à validação automática do modelo de dados e a menos códigos padrão. O suporte do FastAPI para programação assíncrona garante que as APIs sejam eficientes e escaláveis, enquanto os recursos de documentação integrados, como o MongoDB UI e o ReDoc, fornecem ferramentas interativas de pesquisa da API.
O FastAPI se integra perfeitamente ao MongoDB por meio da biblioteca Motor, permitindo interações assíncronas com o banco de dados. Essa combinação oferece suporte a aplicativos escaláveis, aumentando a velocidade e a flexibilidade do tratamento de dados com o MongoDB. FastAPI e MongoDB juntos são ideais para criar aplicativos que gerenciam quantidades potencialmente grandes de dados complexos e diversos de forma eficiente. O MongoDB é um padronizadorsortudo do projeto FastAPI, então você pode perceber que é uma ótima opção para criar aplicativos com o MongoDB.
Todas as técnicas descritas neste artigo estão disponíveis no GitHub — confira o código-fonte! Com isso fora do caminho, agora podemos começar...
O FastAPI é particularmente adequado para criar APIs RESTful, em que solicitações de dados e atualizações no banco de dados são feitas usando solicitações HTTP, geralmente com cargas JSON. Mas a estrutura é igualmente excelente como back-end para sites HTML ou até mesmo aplicativos completos de página única (SPAs), onde a maioria das solicitações é feita via JavaScript. (Chamamos isso de pilha FARM — FastAPI, React, MongoDB — mas você pode trocar qualquer estrutura de componente front-end que desejar.) É particularmente flexível em relação ao back-end do banco de dados e à linguagem de modelo usada para renderizar HTML.

Use o driver correto!

Na verdade, existem dois drivers Python para MongoDB – PyMongo e Motor – mas apenas um deles é adequado para uso com FastAPI. Como o FastAPI é construído sobre ASGI e asyncio, você precisa usar o Motor, que é compatível com asyncio. O PyMongo é apenas para aplicativos síncronos. Felizmente, assim como o PyMongo, o Motor é desenvolvido e totalmente suportado pelo MongoDB, então você pode confiar nele na produção, assim como faria com o PyMongo.
Você pode instalá-lo executando o seguinte comando em seu terminal (recomendo configurar um ambiente virtual Python primeiro!):
1pip install motor[srv]
O extrasrv inclui algumas dependências extras que são necessárias para a conexão com cadeias de conexão do MongoDB Atlas.
Depois de instalado, você precisará usar o AsyncIOMotorClient no pacotemotor.motor_asyncio.
1from fastapi import FastAPI
2from motor.motor_asyncio import AsyncIOMotorClient
3
4app = FastAPI()
5
6# Load the MongoDB connection string from the environment variable MONGODB_URI
7CONNECTION_STRING = os.environ['MONGODB_URI']
8
9# Create a MongoDB client
10client = AsyncIOMotorClient(CONNECTION_STRING)
Observe que a cadeia de conexão não é armazenada no código! O que me leva a...

Mantenha seus segredos seguros

É muito fácil confirmar acidentalmente credenciais secretas em seu código e enviá-las para locais relativamente inseguros, como repositórios compartilhados do Git. Recomendo que você crieo hábito denunca colocar nenhum segredo em seu código.
Ao trabalhar com código, guardo meus segredos em um arquivo chamado .envrc — o conteúdo é carregado em variáveis de ambiente por uma ferramenta chamada direnv. Outras ferramentas para manter credenciais confidenciais fora do seu código incluem o envdir, uma biblioteca como o python-dotenv, e há várias ferramentas como oHoncho e oForeman. Você deve usar qualquer ferramenta que faça mais sentido para você. Se o arquivo que mantém seus segredos é chamado .env ou .envrc ou qualquer outra coisa, você deve adicionar esse nome de arquivo ao seu arquivogitignore global para que ele nunca seja adicionado a nenhum repositório.
Na produção, você deve usar um KMS (sistema de gerenciamento de chaves) como o Vaultou talvez o KMS nativo na cloud de qualquer cloud que você esteja usando para hospedar seu aplicativo. Algumas pessoas até usam um KMS para gerenciar seus segredos em desenvolvimento.

Inicialize sua conexão de banco de dados corretamente

Embora eu tenha inicializado minha conexão de banco de dados no código acima no nível superior de um pequeno aplicativo FastAPI, é uma prática recomendada inicializar e fechar normalmente a conexão do cliente, respondendo a eventos de inicialização e desligamento em seu aplicativo FastAPI. Você também deve anexar seu cliente ao objeto de aplicativo do FastAPI para disponibilizá-lo às suas funções de operação de caminho, onde quer que elas estejam em sua base de código. (Outras estruturas às vezes se referem a elas como “routes” ou “endpoints.”. A FastAPI as chama de “path operations.”) Se você confiar em uma variável global, precisará se preocupar em importá-la em todos os lugares necessários, o que pode ser confuso.
O trecho de código abaixo mostra como responder ao início e ao desligamento do seu aplicativo e como lidar com o cliente em resposta a cada um desses eventos:
1from contextlib import asynccontextmanager
2from logging import info @asynccontextmanager
3async def db_lifespan(app: FastAPI):
4 # Startup
5 app.mongodb_client = AsyncIOMotorClient(CONNECTION_STRING)
6 app.database = app.mongodb_client.get_default_database()
7 ping_response = await app.database.command("ping")
8 if int(ping_response["ok"]) != 1:
9 raise Exception("Problem connecting to database cluster.")
10 else:
11 info("Connected to database cluster.")
12
13 yield
14
15 # Shutdown
16 app.mongodb_client.close()
17
18
19app: FastAPI = FastAPI(lifespan=db_lifespan)

Considere usar um ODM Pydantial

Um ODM, ou mapeador de documentos de objetos, é uma biblioteca que converte entre documentos e objetos em seu código. É em grande parte análogo a um ORM no mundo dos bancos de dados RDBMS. O uso de um ODM é um tópico complexo e, às vezes, ele pode ocultar coisas importantes, como a forma como os dados são armazenados e atualizados no banco de dados ou até mesmo alguns recursos avançados do MongoDB que você pode querer aproveitar. Seja qual for o ODM que você escolher, você deve examiná-lo altamente para ter certeza de que ele fará o que você deseja e crescerá com você.
Se você estiver escolhendo um ODM para seu aplicativo FastAPI, considere definitivamente o uso de um ODM baseado em Pydants , como ODMantic ouBeanie. A razão pela qual você deve preferir uma dessas bibliotecas é que a FastAPI foi construída com total integração com o Pydatatic. Isso quer Além de documentar sua interface, ele também fornece validação dos dados que você está retornando.
1class Profile(Document):
2 """
3 A profile for a single user as a Beanie Document.
4
5 Contains some useful information about a person.
6 """
7
8 # Use a string for _id, instead of ObjectID:
9 id: Optional[str] = Field(default=None, description="MongoDB document ObjectID")
10 username: str
11 birthdate: datetime
12 website: List[str]
13
14 class Settings:
15 # The name of the collection to store these objects.
16 name = "profiles"
17
18# A sample path operation to get a Profile:
19@app.get("/profiles/{profile_id}")
20async def get_profile(profile_id: str) -> Profile:
21 """
22 Look up a single profile by ID.
23 """
24 # This API endpoint demonstrates using Motor directly to look up a single
25 # profile by ID.
26 profile = await Profile.get(profile_id)
27 if profile is not None:
28 return profile
29 else:
30 raise HTTPException(
31 status_code=404, detail=f"No profile with id '{profile_id}'"
32 )
O objeto de perfil acima é documentado automaticamente no caminho "/docs":
Uma captura de tela da documentação gerada automaticamente

Você pode usar o Motor diretamente

Se você acha que trabalhar diretamente com o driver do Python MongoDB, Motor, faz mais sentido para você, posso lhe garantir que ele funciona muito bem para muitos aplicativos MongoDB grandes e complexos em produção. Se você ainda quiser os benefícios da documentação automatizada da API, poderá documentar seu esquema em seu código para que ele seja escolhido pelo FastAPI.

Lembre-se de que alguns BSON têm mais tipos do que JSON

Como muitos aplicativos FastAPI incluem endpoints que fornecem dados JSON que são recuperados do MongoDB, é importante lembrar que determinados tipos que você pode armazenar em seu banco de dados, especialmente os tipos ObjectID e Binary, não existem no JSON. Felizmente, a FastAPI lida com datas e horários para você, codificando-os como strings formatadas.
Existem algumas maneiras diferentes de lidar com mapeamentos ObjectID. A primeira é evitá-los completamente usando um tipo compatível com JSON (como uma string) para valores de ID. Em muitos casos, isso não é prático, porque você já tem dados ou apenas porque o ObjectID é o tipo mais apropriado para sua chave primária. Nesse caso, você provavelmente desejará converter ObjectIDs em uma representação de string ao converter para JSON e fazer o inverso com dados que estão sendo enviados para seu aplicativo.
Se você estiver usando Beanie, ele assumirá automaticamente que o tipo do seu _id é um ObjectID e, portanto, definirá o tipo de campo como PydanticObjectId, que tratará automaticamente desse mapeamento de serialização para você. Você nem precisará declarar o id no seu modelo!

Defina tipos de Pydantials para suas respostas de operação de caminho

Se você especificar o tipo de resposta de suas operações de caminho, a FastAPI validará as respostas fornecidas e também filtrará todos os campos que não estejam definidos no tipo de resposta.
Como aDomantic e aBeanie usam o Pydantic sob o capô, você pode devolver esses objetos diretamente. Aqui está um exemplo usando Beanie:
1@app.get("/people/{profile_id}")
2async def read_item(profile_id: str) -> Profile:
3 """ Use Beanie to look up a Profile. """
4 profile = await Profile.get(profile_id)
5 return profile
Se você estiver usando o Motor, ainda poderá obter os benefícios de documentação, conversão, validação e filtragem retornando dados do documento, mas fornecendo o modelo Pydantic ao decorador:
1@app.get(
2 "/people/{profile_id}",
3 response_model=Profile,
4)
5async def read_item(profile_id: str) -> Mapping[str, Any]:
6 # This API endpoint demonstrates using Motor directly to look up a single
7 # profile by ID.
8 #
9 # It uses response_model (above) to tell FastAPI the schema of the data
10 # being returned, but it returns a dict directly, so that conversion and
11 # validation is done by FastAPI, meaning you don't have to copy values
12 # manually into a Profile before returning it.
13 profile = await app.profiles.find_one({"_id": profile_id})
14 if profile is not None:
15 return profile

Lembre-se de modelar seus dados adequadamente

Um erro comum que as pessoas cometem ao construir servidores de API RESTful no MongoDB é armazenar os objetos de sua interface API exatamente da mesma maneira em seu MongoDB database. Isso pode funcionar muito bem em casos simples, especialmente se o aplicativo for uma API CRUD relativamente direta.
Em muitos casos, no entanto, você vai querer pensar sobre a melhor forma de modelar seus dados para atualizações e recuperação eficientes e ajudar a manter a integridade referencial e índices de tamanho razoável. Este é um tópico próprio, então, certifique-se de conferir a série de artigos sobre padrões de design no site do MongoDB e, talvez, considere fazer o curso online gratuito Advanced Schema Design Padrões na MongoDB University. (Existem muitos cursos gratuitos incríveis sobre diversos tópicos na MongoDB University.)
Se estiver trabalhando com um modelo de dados diferente no banco de dados e no aplicativo, será necessário mapear os valores recuperados do banco de dados e os valores fornecidos por meio de solicitações às operações do caminho da API. Separar o modelo físico do modelo de negócios tem a vantagem de permitir que você altere o esquema do banco de dados sem necessariamente alterar o esquema da API (e vice-versa).
Mesmo que você não esteja mapeando dados retornados do banco de dados (Ainda), fornecer uma classe Pydentic como response_model para sua operação de caminho converterá, validará, documentará e filtrará os campos dos dados BSON que você está retornando, então ele fornece muito valor! Aqui está um exemplo de uso desta técnica em um aplicativo FastAPI:
1# A Pydantic class modelling the *response* schema.
2class Profile(BaseModel):
3 """
4 A profile for a single user.
5 """
6 id: Optional[str] = Field(
7 default=None, description="MongoDB document ObjectID", alias="_id"
8 )
9 username: str
10 residence: str
11 current_location: List[float]
12
13# A path operation that returns a Profile object as JSON:
14@app.get(
15 "/profiles/{profile_id}",
16 response_model=Profile, # This tells FastAPI that the returned object must match the Profile schema.
17)
18async def get_profile(profile_id: str) -> Mapping[str, Any]:
19 # Uses response_model (above) to tell FastAPI the schema of the data
20 # being returned, but it returns a dict directly, so that conversion and
21 # validation is done by FastAPI, meaning you don't have to copy values
22 # manually into a Profile before returning it.
23 profile = await app.profiles.find_one({"_id": profile_id})
24 if profile is not None:
25 return profile # Return BSON document (Mapping). Conversion etc will be done automatically.
26 else:
27 raise HTTPException(
28 status_code=404, detail=f"No profile with id '{profile_id}'"
29 )

Use o FastAPI e o MongoDB Generator de pilha completa

Seus incríveis colaboradores criaram um gerador de aplicativos para fazer muitas dessas coisas por você e ajudá-lo a entrar em operação o mais rápido possível com um serviço FastAPI, React e MongoDB dockerizado e de qualidade de produção, apoiado por testes e integração contínua. Você pode conferir no repositório do Full-Stack FastAPI MongoDB no Github .
A página inicial de um aplicativo criado com o Gerador FastAPI

Conclusão

Esperemos que este artigo tenha fornecido a você o conhecimento para criar um aplicativo FastAPI que seja dimensionado tanto para a quantidade de código que você escreve quanto para os dados que você precisa armazenar. Estamos sempre procurando por mais truques e dicas para criar aplicativos com FastAPI e MongoDB, então, se você tiver algumas sugestões, por que não abrir um ticket no Github e conversamos?

Queremos saber o que você está construindo!

Gostamos de saber o que você está construindo com a FastAPI ou qualquer outra framework — seja um projeto de passatempo ou um aplicativo empresarial que vai mudar o mundo. Conte para nós o que você está construindo nos MongoDB Community. Também é um ótimo lugar para passar se você estiver com problemas — alguém nos fóruns provavelmente pode ajudá-lo!
Principais comentários nos fóruns
Avatar do Comentarista do Fórum
Alessio_RuggiAlessio Ruggilast quarter

Estou comentando apenas para apontar que o link para o Github parece não funcionar

Veja mais nos fóruns

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Construindo com padrões: o padrão Subset


Sep 23, 2022 | 3 min read
Tutorial

Design de esquema do MongoDB: melhores práticas de modelagem de dados


Oct 01, 2024 | 11 min read
Início rápido

Construindo aplicativos Rails com o modelo MongoDB


Aug 26, 2024 | 4 min read
Tutorial

Construindo com padrões: o padrão computado


May 16, 2022 | 3 min read
Sumário