Εκμάθηση: Δημιουργήστε έναν στατικό χάρτη χρησιμοποιώντας REST API και Python

Fabric Οι χάρτες ορίζονται από έναν δημόσιο ορισμό (map.json) που περιγράφει τον βασικό χάρτη, τις πηγές δεδομένων, τις προελεύσεις επιπέδων και τη συμπεριφορά απόδοσης.

Αυτό το εκπαιδευτικό βοήθημα παρουσιάζει ένα σενάριο στατικών δεδομένων χρησιμοποιώντας αρχεία που είναι αποθηκευμένα σε ένα Lakehouse. Για σενάρια ροής σε πραγματικό χρόνο με χρήση του Eventstream και του Eventhouse, ανατρέξτε στο θέμα Δημιουργήστε έναν χάρτη σε πραγματικό χρόνο χρησιμοποιώντας REST API και Python.

Ο πιο αξιόπιστος τρόπος για να αυτοματοποιήσετε τη δημιουργία χάρτη είναι να παρέχετε τον ορισμό του χάρτη ενσωματωμένο, έτσι ώστε ο χάρτης να είναι πλήρως διαμορφωμένος και έτοιμος για απόδοση κατά τη δημιουργία.

Για περισσότερες πληροφορίες σχετικά με τη δομή ορισμού χάρτη, δείτε Ορισμός στοιχείου χάρτη.

Χρησιμοποιώντας το Fabric REST API:

  • Δημιουργήστε ένα Lakehouse χρησιμοποιώντας το Fabric REST API
  • Αποστολή αρχείου GeoJSON στο OneLake
  • Αποστολή προσαρμοσμένου εικονιδίου δείκτη SVG στο OneLake
  • Δημιουργήστε έναν ορισμό map.json που αναφέρεται σε δεδομένα Lakehouse
  • Δημιουργία χάρτη με ενσωματωμένο τον ορισμό που παρέχεται

Αυτό το σεμινάριο ακολουθεί ένα κοινό μοτίβο αυτοματισμού στο Fabric: δημιουργία υποδομής → μεταφόρτωση δεδομένων → ορισμός οπτικοποίησης → χάρτη απόδοσης.

Πότε να χρησιμοποιήσετε αυτήν την προσέγγιση

Αυτό το μοτίβο είναι καλύτερο για:

  • Στατικά γεωχωρικά σύνολα δεδομένων
  • Επίπεδα αναφοράς (για παράδειγμα, σημεία ενδιαφέροντος, όρια)
  • Ιστορικά δεδομένα ή δεδομένα που υποβάλλονται σε επεξεργασία κατά παρτίδες

Για σενάρια που απαιτούν συνεχή ενημέρωση δεδομένων (για παράδειγμα, ζωντανή παρακολούθηση ή τηλεμετρία), ανατρέξτε Δημιουργήστε έναν χάρτη σε πραγματικό χρόνο χρησιμοποιώντας REST API και Python.

Προϋποθέσεις

  • Python 3.10 ή νεότερη έκδοση
  • Azure CLI
  • Αναγνωριστικό χώρου εργασίας Fabric
  • Δικαιώματα για την κλήση Fabric REST API, όπως:
    • Item.ReadWrite.All

Σημείωμα

Τα ανατεθειμένα εύρη, όπως Item.ReadWrite.All αυτά εκχωρούνται στην ταυτότητα εισόδου μέσω του ρόλου χώρου εργασίας της. Βεβαιωθείτε ότι στην ταυτότητα που χρησιμοποιείτε το az login έχει εκχωρηθεί ο ρόλος Contributor, Member ή Admin στο χώρο εργασίας προορισμού Fabric πριν από την εκτέλεση της δέσμης ενεργειών.

Έλεγχος ταυτότητας

Αυτό το σεμινάριο χρησιμοποιεί DefaultAzureCredential, το οποίο μπορεί να πραγματοποιήσει έλεγχο ταυτότητας χρησιμοποιώντας πολλές πηγές τοπικών/διαπιστευτηρίων προγραμματιστή. Για τους πρώτους αναγνώστες, η απλούστερη προσέγγιση είναι η είσοδος στο Azure CLI.

  1. Ανοίξτε ένα τερματικό.
  2. Τρέξιμο:
az login

DefaultAzureCredential Μπορείτε να χρησιμοποιήσετε την ταυτότητα που έχετε συνδέσει για να αποκτήσετε διακριτικά πρόσβασης για:

  • API Fabric REST (πόρος: https://api.fabric.microsoft.com/.default)
  • Πρόσβαση στο OneLake μέσω API και SDK ADLS Gen2, συμπεριλαμβανομένης της διευθυνσιοδότησης βάσει GUID για χώρους εργασίας και στοιχεία.

Συμβουλή

Σχετικά με https://api.fabric.microsoft.com/.default Αυτή η τιμή είναι μια εμβέλεια αίτησης διακριτικού και όχι μια διεύθυνση URL που καλείτε απευθείας. Ενημερώνει το Microsoft Entra ότι το διακριτικό πρόσβασης θα πρέπει να εκδοθεί για το Microsoft Fabric REST API και θα πρέπει να περιλαμβάνει όλα τα δικαιώματα Fabric που έχουν ήδη εκχωρηθεί στην ταυτότητα που έχει υποβληθεί σε έλεγχο ταυτότητας (όπως Item.ReadWrite.All ή Workspace.ReadWrite.All).

Το .default πεδίο εφαρμογής χρησιμοποιείται μόνο κατά την απόκτηση διακριτικού και δεν αποστέλλεται ποτέ σε τελικά σημεία API Fabric REST.

Για περισσότερες πληροφορίες σχετικά με τον τρόπο λειτουργίας του .default πεδίου εφαρμογής στην πλατφόρμα ταυτοτήτων της Microsoft, ανατρέξτε στο θέμα Εμβέλειες και δικαιώματα στην πλατφόρμα ταυτοτήτων της Microsoft.

Πριν εκτελέσετε αυτό το πρόγραμμα εκμάθησης, συνιστούμε να εισέλθετε στο Microsoft Fabric τουλάχιστον μία φορά:

https://app.fabric.microsoft.com

Η είσοδος διασφαλίζει ότι η ταυτότητα Fabric, η ιδιότητα μέλους ρόλου χώρου εργασίας και οι εκχωρήσεις εκχωρημένων πόρων παρέχονται πλήρως πριν από την απόκτηση ενός διακριτικού πρόσβασης Microsoft Entra μέσω προγραμματισμού.

Αυτό το βήμα είναι ιδιαίτερα χρήσιμο εάν:

  • Είστε νέος χρήστης του Microsoft Fabric
  • Ο χώρος εργασίας δημιουργήθηκε πρόσφατα
  • Η ανάθεση ρόλου προστέθηκε πρόσφατα

Σημείωμα

Αυτό το σεμινάριο πραγματοποιεί έλεγχο ταυτότητας χρησιμοποιώντας το Microsoft Entra ID μέσω DefaultAzureCredential. Τα Fabric REST API δεν απαιτούν περίοδο λειτουργίας προγράμματος περιήγησης, αλλά η είσοδος στην εμπειρία web του Fabric μπορεί να αποτρέψει προβλήματα εξουσιοδότησης πρώτης εκτέλεσης που προκαλούνται από καθυστερημένη παροχή ρόλων.

Δημιουργήστε το αρχείο GeoJSON

Το αρχείο GeoJSON σε αυτό το σεμινάριο χρησιμοποιείται ως επίπεδο δεδομένων του χάρτη. Αφού δημιουργήσετε το αρχείο, ενημερώστε τη local_geojson_path μεταβλητή ώστε να αντικατοπτρίζει τη σωστή διαδρομή.

Αντιγράψτε το ακόλουθο GeoJSON σε ένα κενό αρχείο κειμένου και αποθηκεύστε το αρχείο ως starbucks-seattle.geojson:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 999 3rd Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334389, 47.605278] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1201 3rd Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.335167, 47.608040] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 221 Pike St" },
      "geometry": { "type": "Point", "coordinates": [-122.340057, 47.609450] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 800 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.330048, 47.604550] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1420 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334091, 47.610041] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1524 7th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334915, 47.614498] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2011 7th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.338165, 47.616341] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2001 8th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.338806, 47.616848] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 4147 University Way NE" },
      "geometry": { "type": "Point", "coordinates": [-122.313873, 47.658298] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2200 NW Market St" },
      "geometry": { "type": "Point", "coordinates": [-122.384056, 47.668581] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 101 Broadway E" },
      "geometry": { "type": "Point", "coordinates": [-122.320457, 47.620480] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 824 E Pike St" },
      "geometry": { "type": "Point", "coordinates": [-122.320282, 47.614212] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 6501 California Ave SW" },
      "geometry": { "type": "Point", "coordinates": [-122.387016, 47.545376] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1501 4th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.336212, 47.610325] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 701 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.330704, 47.604298] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2344 Eastlake Ave E" },
      "geometry": { "type": "Point", "coordinates": [-122.325874, 47.640884] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 5221 15th Ave NW" },
      "geometry": { "type": "Point", "coordinates": [-122.376595, 47.668210] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 4408 Fauntleroy Way SW" },
      "geometry": { "type": "Point", "coordinates": [-122.377693, 47.564991] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 7303 35th Ave NE" },
      "geometry": { "type": "Point", "coordinates": [-122.290611, 47.682518] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2742 Alki Ave SW" },
      "geometry": { "type": "Point", "coordinates": [-122.408028, 47.579311] }
    }
  ]
}

Σημαντικό

Βεβαιωθείτε ότι η διαδρομή αρχείου που χρησιμοποιείται ταιριάζει local_geojson_path με το σημείο όπου αποθηκεύσατε το αρχείο στον υπολογιστή σας.

Βήμα 1—Δημιουργήστε ένα νέο αρχείο έργου Python

Σε αυτό το βήμα, δημιουργείτε ένα κενό αρχείο Python που θα δημιουργήσετε ενότητα προς ενότητα.

Δημιουργήστε ένα νέο αρχείο με το όνομα:

create_map_from_geojson.py

Ανοίξτε το αρχείο στο πρόγραμμα επεξεργασίας.

Βήμα 2—Εγκαταστήστε τις απαιτούμενες βιβλιοθήκες και προσθέστε τις απαιτούμενες προτάσεις εισαγωγής

Σε αυτό το βήμα, εγκαθιστάτε τις εξαρτήσεις και προσθέτετε τις εισαγωγές που χρησιμοποιεί η δέσμη ενεργειών σας.

Εγκατάσταση απαιτούμενων βιβλιοθηκών

Τρέξιμο:

pip install httpx azure-identity azure-storage-file-datalake

Σε τι χρησιμεύει κάθε βιβλιοθήκη

  • httpx: κάνει αιτήσεις HTTP στα API REST του Fabric.
  • azure-identity: παρέχει DefaultAzureCredential για έλεγχο ταυτότητας Microsoft Entra.
  • azure-storage-file-datalake: Αποστέλλει αρχεία στο OneLake χρησιμοποιώντας API συμβατά με ADLS Gen2.

Προσθήκη δηλώσεων εισαγωγής στο αρχείο .py

Στο επάνω μέρος του create_map_from_geojson.py, προσθέστε:

import base64
import json
import os
import time
import uuid
from pathlib import Path

import httpx
from azure.identity import DefaultAzureCredential
from azure.storage.filedatalake import DataLakeServiceClient

Βήμα 3—Προσθήκη ενότητας διαμόρφωσης

Σε αυτό το βήμα, ορίζετε τις μεταβλητές που χρησιμοποιεί η εφαρμογή σας, συμπεριλαμβανομένου του αναγνωριστικού χώρου εργασίας, των διαδρομών αρχείων και των εναλλαγών δυνατοτήτων.

Η συγκέντρωση της ρύθμισης παραμέτρων σε μία μόνο Config κλάση — αντί για τη διασπορά τιμών με ενσωματωμένο κώδικα σε συναρτήσεις — σας δίνει τρία συγκεκριμένα πλεονεκτήματα:

  • Φορητότητα περιβάλλοντος: Τα αναγνωριστικά χώρου εργασίας, οι διαδρομές αρχείων και τα ονόματα πόρων βρίσκονται σε ένα μέρος, ώστε να μπορείτε να εκτελέσετε ξανά τη δέσμη ενεργειών σε διαφορετικό χώρο εργασίας ή υπολογιστή αλλάζοντας μερικές γραμμές (ή μια μεταβλητή περιβάλλοντος) αντί να αναζητήσετε τον κώδικα.
  • Καθαρότερες υπογραφές συναρτήσεων: Οι συναρτήσεις βημάτων δέχονται ένα μεμονωμένο cfg αντικείμενο αντί για μεγάλες λίστες παραμέτρων, γεγονός που διατηρεί την ενορχήστρωση ευανάγνωστη main() .
  • Ασφαλέστερος χειρισμός μυστικών: Οι ευαίσθητες τιμές, όπως το αναγνωριστικό χώρου εργασίας, φορτώνονται από μεταβλητές περιβάλλοντος, επομένως δεν δεσμεύονται ποτέ μαζί με τη δέσμη ενεργειών.

Προσθέστε τα ακόλουθα κάτω από τις δηλώσεις εισαγωγής :

# =========================================================
# Configuration (centralized)
# =========================================================

class Config:
    """
    Central configuration: workspace ID, file paths, resource names, and
    toggles for the optional custom SVG marker. A single instance is built
    in main() and passed to each step function.
    """
    def __init__(self):
        # Workspace
        self.workspace_id = os.environ.get("FABRIC_WORKSPACE_ID", "")
        if not self.workspace_id:
            raise RuntimeError("Set FABRIC_WORKSPACE_ID environment variable before running the script.")

        # Local file (source) and OneLake destination paths (inside Lakehouse Files/)
        self.local_geojson_path = Path(r"C:\tutorial\starbucks-seattle.geojson")
        self.geojson_relative_path = "Files/vector/starbucks-seattle.geojson"

        # Optional SVG marker settings
        self.svg_relative_path = "Files/icons/starbucks-marker.svg"
        self.use_custom_svg_marker = True
        self.builtin_icon_name_fallback = "BuildingShop"

        # SVG content (kept < 1 MB, scales cleanly)
        self.starbucks_marker_svg = """\
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
  <path d="M32 2C20.4 2 11 11.4 11 23c0 15.6 18.7 36.6 19.5 37.5a2 2 0 0 0 3 0C34.3 59.6 53 38.6 53 23 53 11.4 43.6 2 32 2z"
        fill="#006241" stroke="#ffffff" stroke-width="2"/>
  <circle cx="32" cy="23" r="13" fill="#ffffff" opacity="0.95"/>
  <path d="M26 20h12v10c0 3-2.5 5-6 5s-6-2-6-5V20z" fill="#006241"/>
</svg>
"""

        # Resource display names / descriptions
        self.lakehouse_display_name = "lh_starbucks_seattle"
        self.lakehouse_description = "Stores Starbucks Seattle GeoJSON + marker icon for a Fabric Maps tutorial"

        self.map_display_name = "My Fabric Map"
        self.map_description = "Created using Fabric Maps REST API"


Ορισμός του αναγνωριστικού χώρου εργασίας με χρήση μεταβλητής περιβάλλοντος

Αντί να κωδικοποιεί το αναγνωριστικό χώρου εργασίας απευθείας στο σενάριο, αυτό το σεμινάριο το διαβάζει από μια μεταβλητή περιβάλλοντος. Αυτό διατηρεί τις τιμές που αφορούν το περιβάλλον εκτός του πηγαίου κώδικα και σας επιτρέπει να επαναχρησιμοποιήσετε τη δέσμη ενεργειών σε χώρους εργασίας ή μηχανήματα χωρίς να την επεξεργαστείτε.

Πριν εκτελέσετε το σενάριο, δημιουργήστε μια μεταβλητή περιβάλλοντος με το όνομα FABRIC_WORKSPACE_ID.

Σημαντικό

Ένα σύνολο μεταβλητών περιβάλλοντος από ένα τερματικό υπάρχει μόνο μέσα σε αυτήν τη μεμονωμένη περίοδο λειτουργίας τερματικού. Δεν μοιράζεται με άλλα παράθυρα τερματικού, με διαφορετικό τύπο κελύφους ή με διαδικασίες που ξεκινούν εκτός αυτού του τερματικού - συμπεριλαμβανομένων των σεναρίων που ξεκινούν από το κουμπί εκτέλεσης του VS Code, το οποίο συχνά δημιουργεί το δικό του τερματικό. Εάν το σενάριο δεν μπορεί να βρει τη μεταβλητή, αποτυγχάνει με Set FABRIC_WORKSPACE_ID environment variable before running the script.

Για να το αποφύγετε αυτό, είτε εκτελέστε το σενάριο από την ίδια περίοδο λειτουργίας τερματικού όπου ορίζετε τη μεταβλητή, είτε ορίστε την επίμονα (δείτε τις ενότητες Windows και macOS/Linux που ακολουθούν) έτσι ώστε κάθε νέα περίοδος λειτουργίας τερματικού να την λαμβάνει αυτόματα.

Ορισμός της μεταβλητής περιβάλλοντος στα Windows

Στα Windows, μπορείτε να ορίσετε τη μεταβλητή από οποιοδήποτε τερματικό που υποστηρίζει μεταβλητές περιβάλλοντος—PowerShell, Windows PowerShell, PowerShell ή Γραμμή εντολών windows που είναι ενσωματωμένα στο Visual Studio και το Visual Studio Code, το Τερματικό Windows και πολλά άλλα άλλα κοχύλια.

Εκτελέστε τα ακόλουθα στο PowerShell ή στο ενσωματωμένο τερματικό VS Code:

$env:FABRIC_WORKSPACE_ID="<WORKSPACE_ID>"

Για να επιβεβαιώσετε ότι έχει οριστεί η μεταβλητή:

echo $env:FABRIC_WORKSPACE_ID

Με αυτόν τον τρόπο ορίζεται η μεταβλητή μόνο για την τρέχουσα περίοδο λειτουργίας τερματικού.

Ορισμός μόνιμης μεταβλητής περιβάλλοντος (Windows)

Για να είναι διαθέσιμη η μεταβλητή σε μελλοντικές συνεδρίες, χρησιμοποιήστε ένα από τα εξής:

  • PowerShell (one-liner): Εκτέλεση setx FABRIC_WORKSPACE_ID "<WORKSPACE_ID>"αρχείου . Η setx εντολή εγγράφεται στο περιβάλλον χρήστη αλλά δεν ενημερώνει το τρέχον τερματικό—κλείστε και ανοίξτε ξανά το τερματικό (ή ανοίξτε ένα νέο) πριν εκτελέσετε το σενάριο.
  • GUI:
    1. Ανοίξτε τις Ιδιότητες συστήματος.
    2. Επιλέξτε Ρυθμίσεις συστήματος για προχωρημένους.
    3. Επιλέξτε Μεταβλητές περιβάλλοντος.
    4. Στην περιοχή Μεταβλητές χρήστη, επιλέξτε Νέα.
    5. Εισαγάγετε:
      • Όνομα: FABRIC_WORKSPACE_ID
      • Τιμή: το αναγνωριστικό του χώρου εργασίας σας
    6. Επιλέξτε ΟΚ για αποθήκευση.
    7. Κλείστε και ανοίξτε ξανά το τερματικό σας πριν εκτελέσετε ξανά το σενάριο.

Ορισμός της μεταβλητής περιβάλλοντος σε macOS ή Linux

Σε macOS και Linux, μπορείτε να ορίσετε τη μεταβλητή από οποιοδήποτε κέλυφος που υποστηρίζει export—Bash, Zsh (η προεπιλογή στο σύγχρονο macOS), Fish (με ελαφρώς διαφορετική σύνταξη) και τα ενσωματωμένα τερματικά στο Visual Studio Code και σε άλλους επεξεργαστές.

Τρέξιμο:

export FABRIC_WORKSPACE_ID="<WORKSPACE_ID>"

Για να επιβεβαιώσετε ότι έχει οριστεί η μεταβλητή:

echo $FABRIC_WORKSPACE_ID

Με αυτόν τον τρόπο ορίζεται η μεταβλητή μόνο για την τρέχουσα συνεδρία κελύφους.

Ορίστε μια μόνιμη μεταβλητή περιβάλλοντος (macOS ή Linux)

Για να κάνετε τη μεταβλητή διαθέσιμη σε μελλοντικές συνεδρίες, προσθέστε τη export γραμμή στο προφίλ του κελύφους σας:

  • Zsh (προεπιλογή στο macOS): ~/.zshrc
  • Bash: ~/.bashrc (Linux) ή ~/.bash_profile (macOS)
  • Fish: εκτέλεση set -Ux FABRIC_WORKSPACE_ID "<WORKSPACE_ID>" αντί για επεξεργασία αρχείου

Μετά την ενημέρωση του προφίλ, είτε ανοίξτε ένα νέο τερματικό είτε εκτελέστε source ~/.zshrc (ή το κατάλληλο αρχείο), ώστε η αλλαγή να τεθεί σε ισχύ.

Σημείωμα

Οι geojson_relative_path τιμές και svg_relative_path καθορίζουν τη θέση μέσα στην περιοχή Lakehouse Files. Αυτές οι διαδρομές είναι σχετικές με τη ρίζα του Lakehouse και χρησιμοποιούνται τόσο για τη μεταφόρτωση αρχείων όσο και για την αναφορά τους στον ορισμό του χάρτη.

Βήμα 4—Προσθήκη βοηθητικών λειτουργιών

Σε αυτό το βήμα, συνυπολογίζετε τις οριζόντιες ανησυχίες—έλεγχος ταυτότητας, κατασκευή κεφαλίδας, polling μακροχρόνιας λειτουργίας και επαναχρησιμοποιήσιμες μεταφορτώσεις επιπέδου δεδομένων—σε ένα μικρό σύνολο επαναχρησιμοποιήσιμων βοηθών που μπορεί να καλέσει κάθε συνάρτηση βήματος.

Η συγκέντρωση αυτών των ανησυχιών στους βοηθούς - αντί να τις εντάσσετε σε κάθε τοποθεσία κλήσης - σας δίνει τρία συγκεκριμένα πλεονεκτήματα:

  • Μοναδική πηγή αλήθειας για οριζόντιες ανησυχίες: Ο έλεγχος ταυτότητας, οι κεφαλίδες και η ψηφοφορία LRO απαιτούνται σχεδόν σε κάθε κλήση API. Η συγκέντρωσή τους διατηρεί κάθε λειτουργία βήματος εστιασμένη στον δικό της πόρο αντί να εφαρμόζει εκ νέου τη λογική απόκτησης διακριτικών και επανάληψης.
  • Ανθεκτικότητα χωρίς ακαταστασία: Οι βοηθοί απορροφούν παροδικές συνθήκες—ασύγχρονη παροχή, καθυστέρηση μετάδοσης παρασκηνίου, αποτυχίες αποστολής με δυνατότητα επανάληψης—ώστε οι συναρτήσεις βημάτων να παραμένουν σύντομες και να διαβάζονται σαν λίστα ελέγχου.
  • Πιο εύκολο στη διδασκαλία και την τροποποίηση: Κάθε βοηθός εισάγεται μία φορά και επαναχρησιμοποιείται. Εάν το Fabric αλλάξει ένα μοτίβο LRO ή ένα εύρος ελέγχου ταυτότητας, το διορθώνετε σε ένα σημείο.

Οι βοηθοί που προσθέτετε σε αυτό το βήμα είναι:

  • Βοηθοί ελέγχου ταυτότητας: δημιουργία κεφαλίδων για Fabric API REST (και Power BI τελικά σημεία LRO συμπλέγματος)
  • FabricClient: ελαφρύ περιτύλιγμα για συνεπείς κλήσεις API
  • LRO handler: poll μακροχρόνιες λειτουργίες χρησιμοποιώντας Location / x-ms-operation-id / Retry-After, συμπεριλαμβανομένων των αποκρίσεων 200-with-Running, των τελικών σημείων συμπλέγματος Power BI και των ωφέλιμων φορτίων ολοκλήρωσης μόνο κατάστασης (επιλύεται από το displayName)
  • Βοηθός ωφέλιμου φορτίου ορισμού: κωδικοποίηση base64 map.json για ενσωματωμένους ορισμούς
  • Βοηθοί μεταφόρτωσης OneLake: αποστολή αρχείων GeoJSON και SVG σε αρχεία Lakehouse με επανάληψη

Σημείωμα

Αυτό το εκπαιδευτικό βοήθημα εκτείνεται σε δύο επίπεδα:

  • Επίπεδο ελέγχου (Fabric REST API): δημιουργία στοιχείων Lakehouse και χάρτη
  • Επίπεδο δεδομένων (OneLake DFS): αποστολή αρχείων στο Lakehouse

Απαιτούνται και τα δύο για την πλήρη ρύθμιση του χάρτη.

Δημιουργία βοηθητικών λειτουργιών ελέγχου ταυτότητας

Κάθε Fabric κλήση REST που πραγματοποιεί αυτό το σεμινάριο φέρει ένα διακριτικό πρόσβασης Microsoft Entra (διακριτικό κομιστή) στην κεφαλίδα Authorization. Αντί να αποκτά διακριτικά ad hoc, αυτό το βήμα τυλίγεται DefaultAzureCredential σε ένα μικρό TokenProvider και εκθέτει ένα πρόγραμμα δημιουργίας κεφαλίδων για συγκεκριμένο κοινό για κάθε οικογένεια τελικού σημείου που καλεί το σενάριο.

Η συγκέντρωση της απόκτησης διακριτικών και της κατασκευής κεφαλίδων σε βοηθούς — αντί να αποκτάτε διακριτικά σε κάθε τοποθεσία κλήσης — σας δίνει τρία συγκεκριμένα πλεονεκτήματα:

  • Κεντρικό διαπιστευτήριο: Ένα μεμονωμένο DefaultAzureCredential τυλίγεται στο TokenProvider και επαναχρησιμοποιείται για κάθε κλήση API, επομένως η ανακάλυψη ταυτότητας (Azure CLI, VS Code, διαχειριζόμενη ταυτότητα κ.λπ.) γίνεται μία φορά.
  • Διακριτικά με επίγνωση κοινού: Fabric API REST και Power BI τελικά σημεία LRO συμπλέγματος απαιτούν διακριτικά που εκδίδονται για διαφορετικά είδη κοινού. Ένα ξεχωριστό εργαλείο δημιουργίας κεφαλίδων ανά κοινό διατηρεί το σωστό εύρος ακριβώς δίπλα στον ιστότοπο κλήσης, επομένως είναι προφανές σε ποιο τελικό σημείο στοχεύει κάθε συνάρτηση.
  • Φρέσκο σε κάθε αίτημα: Οι δημιουργοί κεφαλίδων κατασκευάζουν την Authorization κεφαλίδα κατ' απαίτηση αντί να αποθηκεύουν οι ίδιοι το διακριτικό στην προσωρινή μνήμη. Τα υποκείμενα διαπιστευτήρια ανανεώνονται με διαφάνεια, επομένως οι ιστότοποι κλήσεων δεν χρειάζεται ποτέ να σκεφτούν τη λήξη.

Αυτό το εκπαιδευτικό βοήθημα καλεί Fabric REST API χρησιμοποιώντας ανατεθειμένα πεδία όπως Item.ReadWrite.AllLakehouse.ReadWrite.All για λειτουργίες που αφορούν το Lakehouse).

Προσθέστε τα ακόλουθα μετά το Config μάθημα:

# =========================================================
# Auth helpers
#
# Authentication utilities built on `DefaultAzureCredential` that acquire and
# construct Authorization headers for calling Fabric REST APIs.
# =========================================================

class TokenProvider:
    """
    Thin wrapper around `DefaultAzureCredential` that acquires Entra access
    tokens. `_fabric_headers()` and `_pbi_headers()` call `get()` per
    request so the Authorization header is always fresh; the underlying
    credential refreshes transparently.
    """
    def __init__(self):
        self._cred = DefaultAzureCredential()

    def get(self, scope: str) -> str:
        return self._cred.get_token(scope).token


_tokens = TokenProvider()


def _fabric_headers() -> dict[str, str]:
    """
    Build headers for Fabric REST API calls.

    This function is called each time we make a Fabric REST call so the token is fresh.
    """
    return {
        "Authorization": f"Bearer {_tokens.get('https://api.fabric.microsoft.com/.default')}",
        "Content-Type": "application/json"
    }


def _pbi_headers() -> dict[str, str]:
    """
    Build headers for polling Power BI cluster LRO endpoints
    (e.g., df-*.analysis.windows.net) that require a Power BI audience token.
    """
    return {
        "Authorization": f"Bearer {_tokens.get('https://analysis.windows.net/powerbi/api/.default')}",
        "Content-Type": "application/json"
    }

Σημείωμα

Ορισμένες Fabric μακροχρόνιες λειτουργίες (LRO) φιλοξενούνται σε τελικά σημεία συμπλέγματος Power BI (*.analysis.windows.net) και όχι σε api.fabric.microsoft.com. Αυτά τα τελικά σημεία απαιτούν ένα διακριτικό κοινού Power BI, επομένως ο βοηθός LRO μεταβαίνει αυτόματα σε _pbi_headers() όταν εντοπίζει αυτήν τη διεύθυνση URL ανίχνευσης.

Δημιουργία περιτυλίγματος προγράμματος-πελάτη Fabric

Οι περισσότερες κλήσεις REST Fabric σε αυτό το σεμινάριο στέλνουν τις ίδιες κεφαλίδες Authorization και Content-Type. Αντί να τα επαναλαμβάνει σε κάθε τοποθεσία κλήσης, αυτό το σεμινάριο τυλίγεται httpx.Client σε ένα μικρό FabricClient που επισυνάπτει αυτόματα τις κεφαλίδες ενώ εξακολουθεί να επιστρέφει το ακατέργαστο httpx.Response , ώστε κάθε καλών να μπορεί να επιθεωρήσει τους κωδικούς κατάστασης (για παράδειγμα, για διάκριση 201 από 202το ).

Το περιτύλιγμα με αυτόν τον τρόπο — αντί να περνάτε httpx.Clientheaders=_fabric_headers() σε κάθε τοποθεσία κλήσης — σας δίνει δύο συγκεκριμένα πλεονεκτήματα:

  • Κεφαλίδες σε ένα μέρος: Κάθε τοποθεσία κλήσης λαμβάνει αυτόματα την πιο πρόσφατη _fabric_headers() , επομένως δεν είναι δυνατή η κατά λάθος αποστολή μιας νέας αίτησης χωρίς την Authorization κεφαλίδα.
  • Οι κωδικοί κατάστασης παραμένουν ορατοί: request() επιστρέφει το ακατέργαστο httpx.Response αντί για το αποκωδικοποιημένο JSON, έτσι ώστε οι ιστότοποι κλήσεων να μπορούν ακόμα να διακλαδίζονται στην κατάσταση (201 vs 202) και να επιθεωρούν κεφαλίδες όπως Location ή Retry-After για χειρισμό LRO.

Προσθέστε τα ακόλουθα μετά τις λειτουργίες του βοηθού ελέγχου ταυτότητας:

# =========================================================
# FabricClient (minimal wrapper so call sites stay clean)
# =========================================================

class FabricClient:
    """
    Small wrapper around httpx.Client so we don't repeat headers everywhere.

    Keeps the tutorial behavior:
    - request() returns the raw httpx.Response so the caller can handle 201 vs 202.
    """
    def __init__(self, http_client: httpx.Client):
        self._http = http_client

    def request(self, method: str, url: str, *, json_body=None) -> httpx.Response:
        return self._http.request(method, url, headers=_fabric_headers(), json=json_body)

Δημιουργία βοηθητικής συνάρτησης LRO

Πολλά Fabric API REST που χρησιμοποιούνται σε αυτό το πρόγραμμα εκμάθησης, όπως το Create Lakehouse και το Create Map, υποστηρίζουν long-run operations (LROs).

Αυτά τα API μπορούν να επιστρέψουν απαντήσεις σε διάφορα μοτίβα:

  • 201 Created με το σώμα του πόρου ενσωματωμένο (σύγχρονο)
  • 202 Accepted με μια Location κεφαλίδα που δείχνει σε μια διεύθυνση URL κατάστασης λειτουργίας (ασύγχρονη)
  • 202 Accepted x-ms-operation-id με κεφαλίδα αντί για Location (ασύγχρονη, εναλλακτική μορφή)
  • 200 OK με status: "Running" ή status: "NotStarted" κατά τη διάρκεια της ψηφοφορίας (ακόμα σε εξέλιξη)
  • 200 OKμε status: "Succeeded" αλλά χωρίς αναγνωριστικό πόρου στο σώμα (επιτυχής, επίλυση με καταχώριση και αντιστοίχιση)displayName

Για να χειριστείτε όλα αυτά με συνέπεια, δημιουργείτε μια μοναδική βοηθητική συνάρτηση που:

  1. Επιστρέφει αμέσως το αναγνωριστικό πόρου εάν η αρχική απόκριση το περιέχει ήδη.
  2. Διαφορετικά, σταθμίζει τη διεύθυνση URL της λειτουργίας (που δημιουργήθηκε από ένα ή Locationx-ms-operation-id) χρησιμοποιώντας Retry-After.
  3. Αντιμετωπίζει 200 OK με status: "Running" / "NotStarted" όπως είναι ακόμα σε εξέλιξη και συνεχίζει τη δημοσκόπηση.
  4. Σε περίπτωση επιτυχίας, επιστρέφει το αναγνωριστικό πόρου από το σώμα ή επιστρέφει στην καταχώριση πόρων και στην αντιστοίχιση κατά displayName (με επαναλήψεις) όταν το σώμα είναι μόνο για κατάσταση.
  5. Χρησιμοποιεί _pbi_headers() όταν η διεύθυνση URL ανίχνευσης βρίσκεται σε ένα σύμπλεγμα Power BI (*.analysis.windows.net) και Fabric κεφαλίδες διαφορετικά.

Αυτός ο μοναδικός βοηθός αντικαθιστά την ανάγκη για βοηθούς "επίλυσης με όνομα" ανά πόρο — κάθε create_* συνάρτηση σε αυτό το σεμινάριο καλεί _handle_lro με την κατάλληλη list_url και match_display_name.

Προσθέστε τα ακόλουθα μετά το FabricClient μάθημα:

# =========================================================
# LRO handler 
# =========================================================

def _handle_lro(
    client: httpx.Client,
    initial_response: httpx.Response,
    *,
    list_url: str | None = None,
    match_display_name: str | None = None,
    id_field: str = "id",
    max_attempts: int = 10,
    delay: int = 5,
) -> str:
    """
    Handle a Fabric long-running operation (LRO) and return the resource id.

    Supports the response patterns used by Fabric REST APIs:
    - 200/201 with the resource body inline (synchronous).
    - 202 with a `Location` header or `x-ms-operation-id` (asynchronous).
    - 200 with `status: "Running"` / `"NotStarted"` while polling.
    - 200 with `status: "Succeeded"` but no id (resolve by listing and matching `displayName`).

    Polling uses `Retry-After` and switches to a Power BI audience token when
    the operation URL is on `*.analysis.windows.net`.
    """
    # Sync 200/201 with body: return the id immediately.
    if initial_response.status_code in (200, 201):
        try:
            body = initial_response.json() if initial_response.content else {}
        except ValueError:
            body = {}
        if isinstance(body, dict) and body.get(id_field):
            return body[id_field]

    # Location header, with x-ms-operation-id fallback.
    op_url = initial_response.headers.get("Location")
    if not op_url:
        op_id = initial_response.headers.get("x-ms-operation-id")
        if op_id:
            op_url = f"https://api.fabric.microsoft.com/v1/operations/{op_id}"
        else:
            raise RuntimeError(
                f"Missing LRO Location/x-ms-operation-id. "
                f"status={initial_response.status_code} body={initial_response.text[:500]!r}"
            )

    # Audience-aware polling: Power BI cluster endpoints need a different token.
    poll_headers = _pbi_headers() if "analysis.windows.net" in op_url else _fabric_headers()
    retry_after = int(initial_response.headers.get("Retry-After", "5"))

    while True:
        time.sleep(retry_after)
        poll = client.get(op_url, headers=poll_headers)

        if poll.status_code == 202:
            retry_after = int(poll.headers.get("Retry-After", "5"))
            continue

        poll.raise_for_status()
        body = poll.json() if poll.content else {}
        status = body.get("status") if isinstance(body, dict) else None

        if status in ("Running", "NotStarted"):
            retry_after = int(poll.headers.get("Retry-After", "5"))
            continue
        if status == "Failed":
            raise RuntimeError(f"LRO failed. Body: {body}")

        if isinstance(body, dict) and body.get(id_field):
            return body[id_field]

        # Status-only success: list and match by displayName, with retries.
        if status == "Succeeded" and list_url and match_display_name:
            for attempt in range(max_attempts):
                r = client.get(list_url, headers=_fabric_headers())
                r.raise_for_status()
                match = next(
                    (i for i in r.json().get("value", []) if i.get("displayName") == match_display_name),
                    None,
                )
                if match and match.get(id_field):
                    return match[id_field]
                time.sleep(delay)
            raise RuntimeError(
                f"LRO succeeded but resource not visible after retries. "
                f"match_display_name={match_display_name!r}"
            )

        raise RuntimeError(f"LRO completed but no resource id was returned. Body: {body}")

Σημείωμα

Οι πόροι που δημιουργήθηκαν πρόσφατα ενδέχεται να μην εμφανίζονται αμέσως κατά την κλήση API λίστας λόγω καθυστερήσεων μετάδοσης παρασκηνίου. Η βοηθητική συνάρτηση επαναλαμβάνεται αυτόματα μέχρι να γίνει ορατός ο πόρος.

Βοηθός ωφέλιμου φορτίου ορισμού

Όταν δημιουργείτε έναν χάρτη με δημόσιο ορισμό, το REST API δημιουργίας χάρτη αναμένει ότι κάθε τμήμα θα definition.parts φέρει ένα ωφέλιμο φορτίο με κωδικοποίηση base64 με "payloadType": "InlineBase64". Ο βοηθός _json_to_b64 κωδικοποιεί ένα Python dict (το map.json) σας σε αυτήν τη μορφή, ώστε το create_map να μπορεί να το ρίξει κατευθείαν στο σώμα του αιτήματος.

Προσθέστε τα ακόλουθα μετά τη _handle_lro λειτουργία:

# =========================================================
# Definition payload helper
#
# Encodes map.json as base64 for inline Create map payloads.
# =========================================================

def _json_to_b64(obj: dict) -> str:
    """
    Convert a Python dict to base64-encoded JSON text.

    Fabric Map "Create map with definition inline" requires:
    - definition.parts[].payloadType = InlineBase64
    - definition.parts[].payload     = base64(json(map_json))
    """
    return base64.b64encode(json.dumps(obj).encode("utf-8")).decode("utf-8")

Βοηθοί μεταφόρτωσης OneLake

Το OneLake υποστηρίζει API ADLS/Blob και επιτρέπει τη διευθυνσιοδότηση βάσει GUID για χώρους εργασίας και στοιχεία:

https://onelake.dfs.fabric.microsoft.com/<workspaceGUID>/<itemGUID>/<path>/<fileName>

Προσθήκη:

# ===============================================================================================
# ONE LAKE UPLOAD HELPERS
# OneLake supports GUID-based addressing:
#   https://onelake.dfs.fabric.microsoft.com/<workspaceGUID>/<itemGUID>/<path>/<fileName> 
# We use the ADLS Gen2 SDK (DataLakeServiceClient) to upload files into the Lakehouse Files area.
# ===============================================================================================

def _onelake_client() -> DataLakeServiceClient:
    """
    Build a DataLakeServiceClient against the OneLake DFS endpoint,
    authenticated with `DefaultAzureCredential`. Used by `_upload_with_retry`
    to write files into the Lakehouse Files area.
    """
    return DataLakeServiceClient(
        account_url="https://onelake.dfs.fabric.microsoft.com",
        credential=DefaultAzureCredential()
    )


def _upload_with_retry(
    workspace_guid: str,
    item_guid: str,
    dest_relative_path: str,
    content: bytes,
    attempts: int = 6
) -> None:
    """
    Upload bytes into OneLake at `<workspace GUID>/<item GUID>/<relative path>`.
    Retries with linear backoff because a newly created Lakehouse can
    briefly return errors before its `Files/` area is provisioned.
    """
    service = _onelake_client()
    fs = service.get_file_system_client(file_system=workspace_guid)

    dest_path = f"{item_guid}/{dest_relative_path}".replace("\\", "/")

    last_exc = None
    for i in range(attempts):
        try:
            fs.get_file_client(dest_path).upload_data(content, overwrite=True)
            return
        except Exception as exc:
            last_exc = exc
            time.sleep(2 + i)

    raise RuntimeError(f"Upload failed after {attempts} attempts: {last_exc}")


Συμβουλή

Μπορείτε να επαληθεύσετε ότι το αρχείο στάλθηκε με επιτυχία μεταβαίνοντας στην περιοχή Lakehouse Files στην πύλη Fabric.

Δημιουργία κύριων συναρτήσεων

Στη συνέχεια, προσθέτετε τις κύριες συναρτήσεις που καθορίζουν τη ροή εργασίας. Όλα αυτά ονομάζονται από main().

  1. Δημιουργία lakehouse
  2. Ανεβάστε το GeoJSON στο Lakehouse
  3. Αποστολή προσαρμοσμένου δείκτη SVG (προαιρετικό)
  4. Δημιουργία του ορισμού χάρτη (map.json)
  5. Δημιουργήστε τον χάρτη με τον ορισμό του ενσωματωμένο

Δημιουργία lakehouse

create_lakehouse δημιουργεί το Lakehouse που αποθηκεύει το αρχείο GeoJSON και τον προαιρετικό δείκτη SVG που χρησιμοποιείται από τον χάρτη.

Αυτή η λειτουργία:

  • Στέλνει ένα POST στο τελικό σημείο Lakehouse REST με displayName και description από τη ρύθμιση παραμέτρων σας
  • Μεταβιβάζει την απόκριση στο _handle_lro, το οποίο χειρίζεται ομοιόμορφα τις σύγχρονες (201), τις ασύγχρονες (202/LRO) και τις αποκρίσεις μόνο κατάστασης
  • Επιστρέφει το αναγνωριστικό Lakehouse για χρήση σε επόμενα βήματα

Προσθέστε τα ακόλουθα μετά τη _upload_with_retry λειτουργία:

# =========================================================
# Step 1: Create a Lakehouse
# =========================================================

def create_lakehouse(client: httpx.Client, fabric: FabricClient, cfg: Config) -> str:
    """
    Create a Lakehouse and return its item ID.
    """
    lakehouse_url = f"https://api.fabric.microsoft.com/v1/workspaces/{cfg.workspace_id}/lakehouses"
    lakehouse_payload = {
        "displayName": cfg.lakehouse_display_name,
        "description": cfg.lakehouse_description
    }

    lh_resp = fabric.request("POST", lakehouse_url, json_body=lakehouse_payload)

    lakehouse_id = _handle_lro(
        client,
        lh_resp,
        list_url=lakehouse_url,
        match_display_name=cfg.lakehouse_display_name,
    )

    print("Lakehouse created. Lakehouse ID:", lakehouse_id)
    return lakehouse_id

Ανεβάστε το GeoJSON στο Lakehouse

upload_geojson ανεβάζει το τοπικό αρχείο GeoJSON στην περιοχή Lakehouse Files , όπου γίνεται η πηγή χωρικών δεδομένων που διαβάζει ο χάρτης κατά την απόδοση.

Αυτό είναι το πρώτο βήμα που περνά από το επίπεδο ελέγχου Fabric (REST) στο επίπεδο δεδομένων OneLake (ADLS Gen2). Η συνάρτηση διαβάζει το τοπικό αρχείο στη μνήμη και αναθέτει στο _upload_with_retry, το οποίο εκτελεί την τμηματική μεταφόρτωση DFS και επιχειρεί ξανά σε παροδικά σφάλματα.

Προσθέστε τα ακόλουθα μετά τη create_lakehouse λειτουργία:

# =========================================================
# Step 2: Upload GeoJSON to the Lakehouse
# =========================================================

def upload_geojson(cfg: Config, lakehouse_id: str) -> None:
    """
    Upload the local GeoJSON file to the Lakehouse Files area at
    `cfg.geojson_relative_path` using the OneLake DFS endpoint.
    """
    _upload_with_retry(
        workspace_guid=cfg.workspace_id,
        item_guid=lakehouse_id,
        dest_relative_path=cfg.geojson_relative_path,
        content=cfg.local_geojson_path.read_bytes()
    )
    print("Uploaded GeoJSON to:", cfg.geojson_relative_path)

Αποστολή προσαρμοσμένου δείκτη SVG

upload_svg_marker ανεβάζει ένα προσαρμοσμένο εικονίδιο SVG στο ίδιο Lakehouse, ώστε ο χάρτης να μπορεί να αποδώσει κάθε χαρακτηριστικό με αυτόν τον δείκτη αντί για έναν ενσωματωμένο. Το βήμα είναι προαιρετικό και περικλείεται από cfg.use_custom_svg_marker — όταν η σημαία είναι False, η συνάρτηση επιστρέφει αμέσως και ο χάρτης επιστρέφει σε έναν ενσωματωμένο δείκτη.

Όπως upload_geojson, αυτή η συνάρτηση αναθέτει την πραγματική μεταφόρτωση στο _upload_with_retry.

Προσθέστε τα ακόλουθα μετά τη upload_geojson λειτουργία:

# =========================================================
# Step 3: Upload a custom SVG marker (optional)
# =========================================================

def upload_svg_marker(cfg: Config, lakehouse_id: str) -> None:
    """
    Upload a custom SVG marker to the Lakehouse at
    `cfg.svg_relative_path` when `cfg.use_custom_svg_marker` is True;
    otherwise return without uploading.
    """
    if not cfg.use_custom_svg_marker:
        return

    _upload_with_retry(
        workspace_guid=cfg.workspace_id,
        item_guid=lakehouse_id,
        dest_relative_path=cfg.svg_relative_path,
        content=cfg.starbucks_marker_svg.encode("utf-8")
    )
    print("Uploaded custom SVG marker to:", cfg.svg_relative_path)

Συμβουλή

Οι δείκτες SVG κλιμακώνονται καθαρά σε επίπεδα ζουμ και DPI οθόνης, γεγονός που τους καθιστά κατάλληλους για εικονίδια χάρτη.

Κατασκευάστε map.json

Το build_map_json δημιουργεί και επιστρέφει το φορτίο «map.json που καθορίζει τα περιεχόμενα του Fabric χάρτη. Το ωφέλιμο φορτίο ακολουθεί το σχήμα ορισμού στοιχείων χάρτη και αποτελείται από τέσσερις ενότητες: dataSources (από πού προέρχονται τα δεδομένα), iconSources (προαιρετικοί προσαρμοσμένοι δείκτες), layerSources (τι διαβάζεται και πόσο συχνά) και layerSettings (πώς αποδίδεται το αποτέλεσμα στον χάρτη).

Για αυτό το πρόγραμμα εκμάθησης, dataSources δείχνει το Lakehouse (itemType: "Lakehouse") που δημιουργήθηκε νωρίτερα και η μοναδική καταχώρηση είναι layerSources ένα επίπεδο αρχείου GeoJSON (type: "geojson") που διαβάζει το αρχείο που ανεβάσατε μέσω relativePath. refreshIntervalMs έχει οριστεί σε 0 επειδή το αρχείο προέλευσης είναι στατικό — ο χάρτης αποδίδει το αρχείο μία φορά και δεν κάνει σταθμοσκόπηση για αλλαγές.

Η αντίστοιχη layerSettings καταχώρηση αποδίδει κάθε χαρακτηριστικό ως α marker και εμφανίζει την ιδιότητα GeoJSON name σε συμβουλές εργαλείων. Όταν cfg.use_custom_svg_marker το είναι True, προστίθεται μια iconSources καταχώρηση που αναφέρεται στο SVG που ανεβάσατε και το επίπεδο iconOptions.image χρησιμοποιεί το σύνθετο κλειδί <layerSettingId>:<iconId> για να συνδέσει τον δείκτη σε αυτό το εικονίδιο. Όταν είναι False, το επίπεδο πέφτει πίσω σε έναν ενσωματωμένο δείκτη (cfg.builtin_icon_name_fallback) με στυλ με πράσινο γέμισμα Starbucks.

Για περισσότερες πληροφορίες σχετικά με τον ορισμό χάρτη REST API, ανατρέξτε στην ενότητα Ορισμός στοιχείου χάρτη. Για ένα παράδειγμα map.json, ανατρέξτε στο παράδειγμα MapDetails.

Προσθέστε τα ακόλουθα μετά τη upload_svg_marker λειτουργία:

# =========================================================
# Step 4: Build map.json
# =========================================================

def build_map_json(cfg: Config, lakehouse_id: str) -> dict:
    """
    Build and return the map.json payload for the Fabric Map.

    Wires `dataSources` to the Lakehouse created earlier, defines a
    single GeoJSON layer in `layerSources` that reads the uploaded file
    via `cfg.geojson_relative_path` with `refreshIntervalMs: 0` (the
    source is static), and configures `layerSettings` to render each
    feature as a marker. When `cfg.use_custom_svg_marker` is True, adds
    an `iconSources` entry for the uploaded SVG and binds the layer to
    it via a `<layerSettingId>:<iconId>` composite key; otherwise falls
    back to a built-in marker.
    """
    layer_source_id = str(uuid.uuid4())
    layer_setting_id = str(uuid.uuid4())
    icon_source_id = str(uuid.uuid4())

    custom_svg_marker = f"{layer_setting_id}:{icon_source_id}"
    icon_source_name = "Starbucks Marker"

    map_json = {
        "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/map/definition/2.0.0/schema.json",
        "basemap": {},

        "dataSources": [
            {"itemType": "Lakehouse", "workspaceId": cfg.workspace_id, "itemId": lakehouse_id}
        ],

        "iconSources": (
            [
                {
                    "id": icon_source_id,
                    "name": icon_source_name,
                    "type": "svg",
                    "itemId": lakehouse_id,
                    "relativePath": cfg.svg_relative_path
                }
            ] if cfg.use_custom_svg_marker else []
        ),

        "layerSources": [
            {
                "id": layer_source_id,
                "name": "starbucks_seattle_geojson",
                "type": "geojson",
                "itemId": lakehouse_id,
                "relativePath": cfg.geojson_relative_path,
                "refreshIntervalMs": 0
            }
        ],

        "layerSettings": [
            {
                "id": layer_setting_id,
                "name": "Starbucks (Seattle)",
                "sourceId": layer_source_id,
                "options": {
                    "type": "vector",
                    "visible": True,
                    "tooltipKeys": ["name"],
                    "pointLayerType": "marker",

                    "markerOptions": (
                        {
                            "iconOptions": {
                                "image": custom_svg_marker,
                                "anchor": "bottom",
                                "opacity": 1.0,
                                "rotation": 0,
                                "allowOverlap": False,
                                "rotationAlignment": "viewport",
                                "pitchAlignment": "viewport"
                            },
                            "icon": icon_source_id
                        }
                        if cfg.use_custom_svg_marker
                        else
                        {
                            "size": 22,
                            "fillColor": "#006241",
                            "strokeColor": "#FFFFFF",
                            "strokeWidth": 2,
                            "icon": cfg.builtin_icon_name_fallback,
                            "iconOptions": {
                                "image": f"{layer_setting_id}:{cfg.builtin_icon_name_fallback}",
                                "anchor": "bottom",
                                "opacity": 1.0,
                                "rotation": 0,
                                "allowOverlap": False,
                                "rotationAlignment": "viewport",
                                "pitchAlignment": "viewport"
                            }
                        }
                    )
                }
            }
        ]
    }

    return map_json


Συμβουλή

Συμβουλές σχετικά με τον ορισμό του χάρτη:

  • Η image ιδιότητα χρησιμοποιεί ένα σύνθετο κλειδί στη μορφή <layerSettingId>:<iconId> για να αναφέρει το εικονίδιο για το επίπεδο. Αυτό συσχετίζει τη διαμόρφωση απόδοσης δείκτη με την πηγή εικονιδίου που ορίστηκε νωρίτερα στον ορισμό του χάρτη.
  • Η ρύθμιση refreshIntervalMs σε 0 απενεργοποιεί την αυτόματη ανανέωση. Αυτό είναι κατάλληλο για στατικά αρχεία GeoJSON που είναι αποθηκευμένα σε ένα Lakehouse.

Δημιουργία χάρτη με ενσωματωμένο ορισμό

create_map δημιουργεί τον χάρτη δημοσιεύοντας τον ενσωματωμένο ορισμό που έχετε συγκεντρώσει και επιστρέφει το αναγνωριστικό στοιχείου του νέου χάρτη. Για αυτό το σεμινάριο, το αίτημα φέρει ένα μόνο τμήμα με κωδικοποίηση base64 — map.json — τυλιγμένο ως payloadType: "InlineBase64" και κωδικοποιημένο μέσω _json_to_b64. Το ωφέλιμο map.json φορτίο αναφέρεται ήδη στην προέλευση δεδομένων Lakehouse και, όταν υπάρχει, στο εικονίδιο SVG κατά relativePath, έτσι ώστε το επίπεδο να είναι πλήρως καλωδιωμένο από την κλήση Δημιουργία χάρτη χωρίς επακόλουθο updateDefinition ταξίδι μετ' επιστροφής. Εάν θέλαμε να ορίσουμε μη προεπιλεγμένα μεταδεδομένα στοιχείων ή να καρφιτσώσουμε ένα φιλικό προς το Git logicalId, θα προσθέταμε ένα τμήμα .platform στον ίδιο πίνακα parts. Fabric εφαρμόζει προεπιλεγμένα μεταδεδομένα όταν παραλείπεται το .platform, κάτι που κάνει αυτό το σεμινάριο.

Το Create map REST API μπορεί να απαντήσει με 201 Created (σύγχρονο, ενσωματωμένο αναγνωριστικό), 202 Accepted (ασύγχρονο LRO μέσω Location ή x-ms-operation-id) ή 200 OK με ωφέλιμο φορτίο ολοκλήρωσης μόνο κατάστασης, όπου ο χάρτης δεν είναι ακόμη ορατός στους χάρτες λίστας λόγω καθυστέρησης διάδοσης backend. _handle_lro καλύπτει όλες αυτές τις περιπτώσεις — συμπεριλαμβανομένης της καταχώρισης και της αντιστοίχισης κατά displayName — επομένως αυτή η συνάρτηση αναθέτει τον πλήρη χειρισμό απόκρισης σε αυτήν σε μία μόνο κλήση.

Για περισσότερες πληροφορίες, δείτε Ορισμός στοιχείου αντιστοίχισης.

Προσθέστε τα ακόλουθα μετά τη build_map_json λειτουργία:

# =========================================================
# Step 5: Create a map with inline definition
# =========================================================

def create_map(client: httpx.Client, fabric: FabricClient, cfg: Config, map_json: dict) -> str:
    """
    Create the Fabric map with its definition inline and return its item ID.

    Sends a single Create map request whose `parts` array carries one
    base64-encoded payload, `map.json`. The map definition already
    references the Lakehouse data source (and, when present, the SVG
    icon) by `relativePath`, so the layer is wired by the Create Map
    call without a follow-up update. Delegates response handling to
    `_handle_lro`, which covers synchronous, asynchronous, and
    status-only completions.
    """
    create_map_url = f"https://api.fabric.microsoft.com/v1/workspaces/{cfg.workspace_id}/maps"

    create_map_payload = {
        "displayName": cfg.map_display_name,
        "description": cfg.map_description,
        "definition": {
            "parts": [
                {
                    "path": "map.json",
                    "payload": _json_to_b64(map_json),
                    "payloadType": "InlineBase64"
                }
            ]
        }
    }

    map_resp = fabric.request("POST", create_map_url, json_body=create_map_payload)

    return _handle_lro(
        client, map_resp,
        list_url=create_map_url,
        match_display_name=cfg.map_display_name,
    )

Ενορχηστρώστε τη ροή εργασίας

main είναι το μοναδικό σημείο εισόδου που εκτελεί το σεμινάριο από άκρο σε άκρο. Δημιουργεί Config, ανοίγει ένα httpx.Client επαναχρησιμοποιημένο σε κάθε βοηθό, το τυλίγει σε ένα FabricClient, και στη συνέχεια καλεί κάθε συνάρτηση βήματος με σειρά εξάρτησης: create_lakehouseupload_geojson (γράφει το GeoJSON στο OneLake κάτω από το νέο Lakehouse) → upload_svg_marker (προαιρετικό, εκτελείται μόνο όταν cfg.use_custom_svg_marker έχει οριστεί) → build_map_jsoncreate_map.

Η ταξινόμηση έχει σημασία επειδή κάθε βήμα καταναλώνει κάτι που δημιουργήθηκε από ένα προηγούμενο βήμα — upload_geojson και upload_svg_marker χρειάζεται το αναγνωριστικό στοιχείου Lakehouse και build_map_json αναφέρεται και στις δύο μεταφορτώσεις relativePath , ώστε η Δημιουργία χάρτη να μπορεί να τις επιλύσει κατά την απόδοση. Το τελικό μπλοκ print εμφανίζει το αναγνωριστικό Lakehouse, το αναγνωριστικό χάρτη και τις σχετικές διαδρομές των απεσταλμένων στοιχείων, ώστε να μπορείτε να τα βρείτε στην πύλη Fabric.

Προσθέστε τα ακόλουθα μετά τη create_map λειτουργία:

# =========================================================
# main(): orchestrates the full workflow
# =========================================================

def main():
    """
    Orchestrate the tutorial workflow.

    1) Create a Lakehouse
    2) Upload GeoJSON to the Lakehouse
    3) Upload a custom SVG marker (optional)
    4) Build the map definition (map.json)
    5) Create the map with its definition inline
    """
    cfg = Config()

    print("Initializing clients...")
    with httpx.Client(timeout=60) as client:
        fabric = FabricClient(client)

        # Step 1
        lakehouse_id = create_lakehouse(client, fabric, cfg)

        # Step 2
        upload_geojson(cfg, lakehouse_id)

        # Step 3 (optional)
        upload_svg_marker(cfg, lakehouse_id)

        # Step 4
        map_json = build_map_json(cfg, lakehouse_id)

        # Step 5
        map_id = create_map(client, fabric, cfg, map_json)

        print("\nDONE")
        print("Lakehouse ID:", lakehouse_id)
        print("Map ID:", map_id)
        print("GeoJSON layer path:", cfg.geojson_relative_path)
        if cfg.use_custom_svg_marker:
            print("Custom SVG marker path:", cfg.svg_relative_path)


if __name__ == "__main__":
    main()

Σε αυτό το σημείο, έχουν οριστεί όλες οι ρυθμίσεις και ο κώδικας.

Στο επόμενο βήμα, εκτελείτε τη δέσμη ενεργειών για να δημιουργήσετε το Lakehouse, να αποστείλετε δεδομένα και να δημιουργήσετε τον χάρτη.

Εκτελέστε την εφαρμογή

Σημείωμα

Τα εμφανιζόμενα ονόματα lakehouse και χάρτη πρέπει να είναι μοναδικά σε έναν χώρο εργασίας. Πριν από την εκ νέου εκτέλεση του σεναρίου, είτε διαγράψτε τα στοιχεία που δημιουργήθηκαν στην προηγούμενη εκτέλεση από τον χώρο εργασίας Fabric είτε αλλάξτε το lakehouse_display_name / map_display_name σε Config. Διαφορετικά, οι κλήσεις δημιουργίας αποτυγχάνουν με 409 ItemDisplayNameAlreadyInUse.

Εκτελέστε τη δέσμη ενεργειών:

python create_map_from_geojson.py

Εάν η δέσμη ενεργειών εκτελεστεί με επιτυχία, θα δείτε έξοδο παρόμοια με τα εξής:

DONE
Lakehouse ID: <Lakehouse ID>
Map ID: <Map ID>
GeoJSON layer path: Files/vector/starbucks-seattle.geojson
Custom SVG marker path: Files/icons/starbucks-marker.svg

Στο Microsoft Fabric, ο χάρτης σας θα πρέπει να μοιάζει με αυτό:

Ένα στιγμιότυπο οθόνης των Χαρτών Microsoft Fabric που εμφανίζουν το Σιάτλ με πολλά πράσινα εικονίδια δεικτών Starbucks συγκεντρωμένα στο κέντρο της πόλης. Ο χάρτης δείχνει δρόμους και υδάτινα στοιχεία με ανοιχτό γκρι φόντο. Ο πίνακας επιπέδων δεδομένων στα αριστερά εμφανίζει το επίπεδο Starbucks (Σιάτλ). Ο χάρτης επικεντρώνεται στο κέντρο του Σιάτλ, συμπεριλαμβανομένης της προκυμαίας του Elliott Bay με δείκτες που υποδεικνύουν μεμονωμένες τοποθεσίες Starbucks που αναφέρονται στο αρχείο εκμάθησης GeoJSON.

Συμβουλή

Εάν ο χάρτης δεν εμφανιστεί αμέσως, ανανεώστε τον χώρο εργασίας ή περιμένετε μερικά δευτερόλεπτα για να ολοκληρωθεί η μετάδοση του backend.

Σύνοψη

Σε αυτό το εκπαιδευτικό βοήθημα, δημιουργήσατε μια αυτοματοποιημένη γεωχωρική λύση χρησιμοποιώντας τους Χάρτες Microsoft Fabric και τα δεδομένα Lakehouse.

Χρησιμοποιήσατε Fabric REST API και Python για να παρέχετε και να ρυθμίσετε όλες τις απαιτούμενες παραμέτρους πόρων και, στη συνέχεια, οπτικοποιήσατε χωρικά δεδομένα που είναι αποθηκευμένα στο OneLake.

Καταφέρατε τα εξής:

  • Αποστολή χωρικών δεδομένων σε Lakehouse
  • Ρύθμιση παραμέτρων συνόλου δεδομένων για γεωχωρική απεικόνιση
  • Δημιούργησε έναν χάρτη Fabric με ενσωματωμένο ορισμό
  • Σύνδεση του χάρτη με δεδομένα Lakehouse
  • Διαμορφωμένα επίπεδα χάρτη για την απόδοση χωρικών χαρακτηριστικών

Αυτή η αρχιτεκτονική επιδεικνύει ένα κοινό μοτίβο δέσμης και ιστορικής χωρικής ανάλυσης στο Fabric:

  • Τα δεδομένα αποθηκεύονται στο OneLake (Lakehouse)
  • Οι χάρτες αναζητούν και αποδίδουν σύνολα χωρικών δεδομένων
  • Τα επίπεδα παρέχουν οπτικές πληροφορίες για γεωγραφικά δεδομένα

Με την αυτοματοποίηση της δημιουργίας πόρων χρησιμοποιώντας Python και REST API, έχετε πλέον μια επαναλαμβανόμενη προσέγγιση για τη δημιουργία γεωχωρικών εφαρμογών που βασίζονται σε στατικά ή ιστορικά σύνολα δεδομένων.

Επόμενα βήματα

Τώρα που καταλαβαίνετε πώς να οπτικοποιήσετε χωρικά δεδομένα από ένα Lakehouse, μπορείτε να επεκτείνετε αυτήν τη λύση:

  • Συνδυάστε πολλαπλά σύνολα δεδομένων για πλουσιότερη γεωχωρική ανάλυση
  • Εφαρμόστε στυλ και φιλτράρισμα για να τονίσετε τάσεις και μοτίβα
  • Προσθήκη επιπέδων αναφοράς, όπως όρια ή δρομολογήσεις
  • Ενοποίηση διοχετεύσεων δεδομένων για αυτόματη ανανέωση συνόλων δεδομένων
  • Εξερευνήστε σενάρια ροής σε πραγματικό χρόνο χρησιμοποιώντας το Eventstream και το Eventhouse

Για περισσότερες πληροφορίες σχετικά με την εργασία με χωρικά δεδομένα και χάρτες στο Fabric, ανατρέξτε στο θέμα:

Για ένα πρόγραμμα εκμάθησης που δείχνει τη δημιουργία ενός χάρτη σε πραγματικό χρόνο χρησιμοποιώντας REST API, ανατρέξτε στο θέμα: