Serverlöst TypeScript-API: Lagra data i MongoDB med Azure Functions
Skapa ett Azure-funktions-API för att lagra data med Mongoose API i Azure Cosmos DB och distribuera sedan funktionsprogrammet till Azure-molnet för värdhantering med en offentlig HTTP-slutpunkt.
Kommentar
Den här artikeln använder programmeringsmodellen Azure Functions Node.js v4 som för närvarande är i förhandsversion.
Förbereda utvecklingsmiljön
Installera följande programvara:
- Skapa en kostnadsfri Azure-prenumeration
- Installera Node.js LTS v18+
- TypeScript v4+
- Azurite installerat globalt för lagring av lokal utveckling
- Azure Functions Runtime v4.16+
- Azure Functions Core Tools v4.0.5095+ (om det körs lokalt) installerat globalt för lokal utveckling
- Installera Visual Studio Code och använd följande tillägg:
1. Logga in på Azure i Visual Studio Code
Om du redan använder Azure-tjänsttilläggen bör du redan vara inloggad och kan hoppa över det här steget.
När du har installerat ett Azure-tjänsttillägg i Visual Studio Code måste du logga in på ditt Azure-konto.
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
I avsnittet Resurser väljer du Logga in på Azure och följer anvisningarna.
När du har loggat in kontrollerar du att e-postadressen för ditt Azure-konto visas i statusfältet och att dina prenumerationer visas i Azure Explorer:
2. Skapa en Azure-resursgrupp
En resursgrupp är en regionbaserad samling resurser. Genom att skapa en resursgrupp och sedan skapa resurser i den gruppen i slutet av självstudien kan du ta bort resursgruppen utan att behöva ta bort varje resurs individuellt.
Skapa en ny mapp i det lokala systemet som ska användas som rot i Azure Functions-projektet.
Öppna den här mappen i Visual Studio Code.
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
Leta upp din prenumeration under Resurser och välj + ikonen och välj sedan Skapa resursgrupp.
Använd följande tabell för att slutföra anvisningarna:
Prompt Värde Ange namnet på den nya resursgruppen. azure-tutorial
Välj en plats för dina nya resurser. Välj en geografisk region nära dig.
3. Skapa den lokala Functions-appen
Skapa ett lokalt Azure Functions-program (serverlöst) som innehåller en HTTP-utlösarfunktion .
Öppna kommandopaletten (Ctrl + Skift + P) i Visual Studio Code.
Sök efter och välj Azure Functions: Skapa nytt projekt .
Använd följande tabell för att slutföra skapandet av det lokala Azure Function-projektet:
Prompt Värde Kommentar Välj den mapp som ska innehålla funktionsprojektet Välj den aktuella mappen (standard). Välj ett språk TypeScript Välj en TypeScript-programmeringsmodell Modell V4 (förhandsversion) Välj en mall för projektets första funktion HTTP-utlösare API:et anropas med en HTTP-begäran. Ange ett funktionsnamn blogposts
API-vägen är /api/blogposts
När Visual Studio Code skapar projektet visar du DIN API-kod i
./src/functions/blogposts.ts
filen.import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; export async function blogposts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function processed request for url "${request.url}"`); const name = request.query.get('name') || await request.text() || 'world'; return { body: `Hello, ${name}!` }; }; app.http('blogposts', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: blogposts });
Den här koden är standardplate i den nya v4-programmeringsmodellen. Det är inte avsett att ange det enda sättet att skriva ett API-lager med POST och GET.
Ersätt den tidigare koden med följande kod så att endast GET-begäranden kan returnera alla blogginlägg.
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; // curl --location 'http://localhost:7071/api/blogposts' --verbose export async function getBlogPosts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); // Empty array for now ... will fix later const blogposts = []; return { status: 200, jsonBody: { blogposts } }; }; app.get('getBlogPosts', { route: "blogposts", authLevel: 'anonymous', handler: getBlogPosts });
Det finns flera azure functions node.js v4-programmeringsmodelländringar i den här koden som du bör notera:
- Funktionsnamnet
getBlobPosts
för , som anger att det är en GET-begäran, hjälper dig att isolera funktionen i loggarna. - Egenskapen
route
är inställd påblogposts
, som är en del av standard-API-vägen,/api/blogposts
. - Egenskapen
methods
har tagits bort och är onödig eftersomapp
objektets användning avget
anger att detta är en GET-begäran. Metodfunktionerna visas nedan. Om du har en annan metod kan du återgå till att användamethods
egenskapen .deleteRequest()
get()
patch()
post()
put()
- Funktionsnamnet
4. Starta azurite lokal lagringsemulator
Utveckla funktioner på din lokala dator kräver antingen en Storage-emulator (kostnadsfri) eller ett Azure Storage-konto (betalt).
Starta den lokala Azurite-lagringsemulatorn i en separat terminal.
azurite --silent --location ./azurite --debug ./azurite/debug.log
Detta krävs för att köra Azure Functions lokalt med hjälp av en lokal Azure Storage-emulator. Den lokala lagringsemulatorn anges i local.settings.json
filen med egenskapen AzureWebJobsStorage med värdet UseDevelopmentStorage=true
.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
}
}
Undermappen azurite
har redan lagts till i .gitignore
filen.
5. Kör den lokala serverlösa funktionen
Kör Azure Functions-projektet lokalt för att testa det innan du distribuerar till Azure.
I Visual Studio Code anger du en brytpunkt för -instruktionen
return
i slutet av funktionen getBlogPosts .I Visual Studio Code trycker du på F5 för att starta felsökningsprogrammet och ansluta till Azure Functions-värden.
Du kan också använda menykommandot Felsöka>startfelsökning.
Utdata visas på terminalpanelen .
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
I avsnittet Arbetsyta letar du upp och expanderar det lokala projektet ->Functions ->getBlogPosts.
Högerklicka på funktionsnamnet, getBlogPosts och välj sedan Kopiera funktions-URL.
I webbläsaren klistrar du in URL:en och väljer Ange eller använder följande cURL-kommando i terminalen:
curl http://localhost:7071/api/blogposts --verbose
Svaret från en tom matris med blogginlägg returneras som:
* Trying 127.0.0.1:7071... * Connected to localhost (127.0.0.1) port 7071 (#0) > GET /api/blogposts HTTP/1.1 > Host: localhost:7071 > User-Agent: curl/7.88.1 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/json < Date: Mon, 08 May 2023 17:35:24 GMT < Server: Kestrel < Transfer-Encoding: chunked < {"blogposts":[]}* Connection #0 to host localhost left intact
Stoppa felsökningsprogrammet Skift + F5 i VS Code.
6. Skapa Azure Function-appen i Visual Studio Code
I det här avsnittet skapar du en funktionsappsmolnresurs och relaterade resurser i din Azure-prenumeration.
Öppna kommandopaletten (Ctrl + Skift + P) i Visual Studio Code.
Sök efter och välj Azure Functions: Skapa funktionsapp i Azure (avancerat) .
Ange följande information i meddelanderutorna:
Prompt Urval Ange ett globalt unikt namn för funktionsappen Skriv ett namn som är giltigt i en URL-sökväg, till exempel first-function
. Postpend 3 tecken för att göra URL:en globalt unik. Namnet du skriver verifieras för att se till att det är unikt i Azure Functions.Välj en körningsstack Välj Node.js 18 LTS eller en senare version. Välj ett operativsystem Välj Linux. Välj en resursgrupp för nya resurser Skapa en ny resursgrupp med namnet azure-tutorial-first-function. Den här resursgruppen kommer så småningom att ha flera resurser: Azure Function, Azure Storage och Cosmos DB for MongoDB API. Välj en värdplan Välj Förbrukning. Välj ett lagringskonto Välj Skapa ett nytt lagringskonto och godkänn standardnamnet. Välj en Application Insights-resurs för din app. Välj Skapa ny Application Insights-resurs och godkänn standardnamnet. Vänta tills meddelandet bekräftar att appen har skapats.
7. Distribuera Azure-funktionsappen till Azure i Visual Studio Code
Viktigt!
Distribution till en befintlig funktionsapp skriver alltid över innehållet i appen i Azure.
- Välj Azure-ikonen i aktivitetsfältet och högerklicka sedan på funktionsappresursen i området Resurser och välj distribuera till funktionsapp.
- Om du tillfrågas om du är säker på att du vill distribuera väljer du Distribuera.
- När distributionen är klar visas ett meddelande med flera alternativ. Välj Visa utdata för att visa resultatet. Om du missar meddelandet väljer du klockikonen i det nedre högra hörnet för att se det igen.
8. Lägg till programinställning i molnappen
Välj Azure-ikonen i aktivitetsfältet och expandera sedan funktionsappresursen i området Resurser och högerklicka på välj Program Inställningar.
Välj Lägg till ny inställning och lägg till följande inställning för att aktivera programmeringsmodellen Node.js v4 (förhandsversion).
Inställning Värde AzureWebJobsFeatureFlags EnableWorkerIndexing
9. Kör fjärrserverlös funktion
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
I avsnittet Resurser expanderar du din Azure Function-appresurs. Högerklicka på funktionsnamnet och välj Kopiera funktions-URL.
Klistra in URL:en i en webbläsare. Samma tomma matris returneras som när du körde funktionen lokalt.
{"blogposts":[]}
10. Lägg till Azure Cosmos DB för MongoDB API-integrering
Azure Cosmos DB tillhandahåller ett MongoDB-API för att tillhandahålla en välbekant integrationsplats.
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
I avsnittet Resurser väljer du + sedan Skapa databasserver. Använd följande tabell för att slutföra anvisningarna för att skapa en ny Azure Cosmos DB-resurs.
Prompt Värde Kommentar Välj en Azure Database Server API för Azure Cosmos DB för MongoDB Ange ett Azure Cosmos DB-kontonamn. cosmosdb-mongodb-database
Lägg till tre tecken för att skapa ett unikt namn. Namnet blir en del av API:ets URL. Välj en kapacitetsmodell. Utan server Välj en resursgrupp för nya resurser. azure-tutorial-first-function Välj den resursgrupp som du skapade i ett tidigare avsnitt. Välj en plats för nya resurser. Välj den rekommenderade regionen.
11. Installera mongoose-beroende
I en Visual Studio Code-terminal, Ctrl + Shift + `, installerar du sedan npm-paketet:
npm install mongoose
12. Lägg till mongoose-kod för blogginlägg
I Visual Studio Code skapar du en underkatalog med namnet lib på
./src/
, skapar en fil med namnet./database.ts
och kopierar följande kod till den.import { Schema, Document, createConnection, ConnectOptions, model, set } from 'mongoose'; const connectionString = process.env.MONGODB_URI; console.log('connectionString', connectionString); const connection = createConnection(connectionString, { useNewUrlParser: true, useUnifiedTopology: true, autoIndex: true } as ConnectOptions); export interface IBlogPost { author: string title: string body: string } export interface IBlogPostDocument extends IBlogPost, Document { id: string created: Date } const BlogPostSchema = new Schema({ id: Schema.Types.ObjectId, author: String, title: String, body: String, created: { type: Date, default: Date.now } }); BlogPostSchema.set('toJSON', { transform: function (doc, ret, options) { ret.id = ret._id; delete ret._id; delete ret.__v; } }); export const BlogPost = model<IBlogPostDocument>('BlogPost', BlogPostSchema); connection.model('BlogPost', BlogPostSchema); export default connection;
Öppna filen i
./src/functions/blogposts
Visual Studio Code och ersätt hela filens kod med följande:import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; import connection from '../lib/database'; // curl --location 'http://localhost:7071/api/blogposts' --verbose export async function getBlogPosts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); const blogposts = await connection.model('BlogPost').find({}); return { status: 200, jsonBody: { blogposts } }; }; app.get('getBlogPosts', { route: "blogposts", authLevel: 'anonymous', handler: getBlogPosts });
13. Lägg till anslutningssträng i den lokala appen
I Azure Explorer i Visual Studio Code väljer du avsnittet Azure Cosmos DB och expanderar för att högerklicka på välj din nya resurs.
Välj Kopiera anslutningssträng.
I Visual Studio Code använder du Utforskaren för att öppna
./local.settings.json
.Lägg till en ny egenskap med namnet
MONGODB_URI
och klistra in värdet för din anslutningssträng.{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "node", "AzureWebJobsFeatureFlags": "EnableWorkerIndexing", "MONGODB_URI": "mongodb://...." } }
Hemligheterna
./local.settings.json
i filen:- Distribueras inte till Azure eftersom det
./.funcignore
ingår i filen. - Är inte incheckad i källkontrollen eftersom den
./.gitignore
ingår i filen.
- Distribueras inte till Azure eftersom det
Kör programmet lokalt och testa API:et med samma URL i föregående avsnitt.
14. Lägg till anslutningssträng i fjärrappen
- Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
- I avsnittet Resurser hittar du din Azure Cosmos DB-instans. Högerklicka på resursen och välj Kopiera Anslut ionssträng.
- I samma resursavsnitt letar du upp funktionsappen och expanderar noden.
- Högerklicka på Program Inställningar och välj Lägg till ny inställning.
- Ange namnet
MONGODB_URI
på appinställningen och välj Retur. - Klistra in det värde som du kopierade och tryck på Retur.
15. Lägg till API:er för att skapa, uppdatera och ta bort blogginlägg
I Visual Studio Code använder du kommandopaletten för att hitta och välja Funktionen Azure Functions: Create.
Välj HTTP-utlösare och ge den
blogpost
namnet (singular).Kopiera följande kod till filen.
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; import connection, { IBlogPost, IBlogPostDocument } from '../lib/database'; // curl -X POST --location 'http://localhost:7071/api/blogpost' --header 'Content-Type: application/json' --data '{"author":"john","title":"my first post", "body":"learn serverless node.js"}' --verbose export async function addBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function addBlogPost processed request for url "${request.url}"`); const body = await request.json() as IBlogPost; const blogPostResult = await connection.model('BlogPost').create({ author: body?.author, title: body?.title, body: body?.body }); return { status: 200, jsonBody: { blogPostResult } }; }; // curl -X PUT --location 'http://localhost:7071/api/blogpost/64568e727f7d11e09eab473c' --header 'Content-Type: application/json' --data '{"author":"john jones","title":"my first serverless post", "body":"Learn serverless Node.js with Azure Functions"}' --verbose export async function updateBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function updateBlogPost processed request for url "${request.url}"`); const body = await request.json() as IBlogPost; const id = request.params.id; const blogPostResult = await connection.model('BlogPost').updateOne({ _id: id }, { author: body?.author, title: body?.title, body: body?.body }); if(blogPostResult.matchedCount === 0) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPostResult } }; }; // curl --location 'http://localhost:7071/api/blogpost/6456597918547e37d515bda3' --verbose export async function getBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); console.log('request.params.id', request.params.id) const id = request.params.id; const blogPost = await connection.model('BlogPost').findOne({ _id: id }); if(!blogPost) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPost } }; }; // curl --location 'http://localhost:7071/api/blogpost/6456597918547e37d515bda3' --request DELETE --header 'Content-Type: application/json' --verbose export async function deleteBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function deleteBlogPost processed request for url "${request.url}"`); const id = request.params.id; const blogPostResult = await connection.model('BlogPost').deleteOne({ _id: id }); if(blogPostResult.deletedCount === 0) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPostResult } }; }; app.get('getBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: getBlogPost }); app.post('postBlogPost', { route: "blogpost", authLevel: 'anonymous', handler: addBlogPost }); app.put('putBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: updateBlogPost }); app.deleteRequest('deleteBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: deleteBlogPost });
Starta den lokala funktionen med felsökningsprogrammet igen. Följande API:er är tillgängliga:
deleteBlogPost: [DELETE] http://localhost:7071/api/blogpost/{id} getBlogPost: [GET] http://localhost:7071/api/blogpost/{id} getBlogPosts: [GET] http://localhost:7071/api/blogposts postBlogPost: [POST] http://localhost:7071/api/blogpost putBlogPost: [PUT] http://localhost:7071/api/blogpost/{id}
Använd API:et
blogpost
(singular) från ett cURL-kommando för att lägga till några blogginlägg.curl -X POST --location 'http://localhost:7071/api/blogpost' --header 'Content-Type: application/json' --data '{"author":"john","title":"my first post", "body":"learn serverless node.js"}' --verbose
Använd API:et
blogposts
(plural) från ett cURL-kommando för att hämta blogginläggen.curl http://localhost:7071/api/blogposts --verbose
16. Visa alla data med Visual Studio Code-tillägget för Azure Cosmos DB
Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
I avsnittet Resurser högerklickar du på din Azure Cosmos DB-databas och väljer Uppdatera.
Expandera testdatabasen och blogposts-samlingsnoderna för att visa dokumenten.
Välj ett av objekten i listan för att visa data i Azure Cosmos DB-instansen.
17. Distribuera om funktionsappen så att den innehåller databaskod
- Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
- I avsnittet Resurser högerklickar du på azure-funktionsappen och väljer Distribuera till funktionsapp.
- I popup-fönstret och frågar om du är säker på att du vill distribuera väljer du Distribuera.
- Vänta tills distributionen är klar innan du fortsätter.
18. Använd molnbaserad Azure-funktion
- I Azure Explorer, i området Funktioner, väljer och expanderar du funktionen och sedan noden Functions , som visar API:erna
- Högerklicka på något av API:erna och välj Kopiera funktions-URL.
- Redigera de tidigare cURL-kommandona för att använda fjärr-URL:en i stället för den lokala URL:en. Kör kommandona för att testa fjärr-API:et.
19. Fråga dina Azure-funktionsloggar
Om du vill söka i loggarna använder du Azure-portalen.
I Visual Studio Code väljer du Azure Explorer. Högerklicka sedan på funktionsappen under Funktioner och välj sedan Öppna i portalen.
Då öppnas Azure-portalen för din Azure-funktion.
Från Inställningar väljer du Application Insights och sedan Visa Application Insights-data.
Den här länken tar dig till din separata måttresurs som du skapade när du skapade din Azure-funktion med Visual Studio Code.
I avsnittet Övervakning väljer du Loggar. Om popup-fönstret Frågor visas väljer du X i det övre högra hörnet i popup-fönstret för att stänga det.
Dubbelklicka på spårningstabellen på fliken Tabeller i fönstret Ny fråga 1.
Detta anger Kusto-frågan
traces
i frågefönstret.Redigera frågan för att söka efter anpassade loggar:
traces | where message startswith "***"
Markera Kör.
Om loggen inte visar några resultat kan det bero på att det är några minuters fördröjning mellan HTTP-begäran till Azure-funktionen och loggtillgängligheten i Kusto. Vänta några minuter och kör frågan igen.
Du behövde inte göra något extra för att få den här loggningsinformationen:
- Koden använde funktionen
context.log
som tillhandahålls av funktionsramverket. Genom att användacontext
i stället förconsole
kan loggningen filtreras till den specifika enskilda funktionen. Det här är användbart om funktionsappen har många funktioner. - Funktionsappen har lagt till Application Insights åt dig.
- Kusto Query-verktyget ingår i Azure-portalen.
- Du kan välja
traces
i stället för att behöva lära dig att skriva en Kusto-fråga för att få minsta möjliga information från loggarna.
- Koden använde funktionen
20. Rensa resurser
Eftersom du använde en enskild resursgrupp kan du ta bort alla resurser genom att ta bort resursgruppen.
- Öppna Azure Explorer i Visual Studio Code genom att välja Azure-ikonen i det primära sidofältet eller använda kortkommandot (Skift + Alt + A).
- Sök efter och välj Azure: Gruppera efter resursgrupp.
- Högerklicka på välj din resursgrupp och välj Ta bort resursgrupp.
- Ange resursgruppens namn för att bekräfta borttagningen.
Källkoden är tillgänglig
Fullständig källkod för den här Azure-funktionsappen:
Nästa steg
Feedback
https://aka.ms/ContentUserFeedback.
Kommer snart: Under hela 2024 kommer vi att fasa ut GitHub-problem som feedbackmekanism för innehåll och ersätta det med ett nytt feedbacksystem. Mer information finns i:Skicka och visa feedback för