Travailler avec des données non structurées dans des volumes
Cette page explique comment stocker, interroger et traiter les fichiers de données non structurées à l'aide de volumes Unity Catalog. Vous apprendrez à upload des fichiers, à interroger les métadonnées, à traiter des fichiers avec des fonctions d'IA, à appliquer le contrôle d'accès et à partager des volumes avec d'autres organisations. Dans la mesure du possible, des instructions pour suivre ce tutoriel à l'aide de l'interface utilisateur de Catalog Explorer ont été incluses. Si aucune option **Catalog Explorer** n'est affichée, utilisez les commandes Python ou SQL fournies.
Pour un aperçu complet des capacités de volume et des cas d'utilisation, voir Que sont les volumes Unity Catalog ?.
Ce tutoriel utilise des fonctions d'IA pour traiter les fichiers par chemin d'accès. Disponible en version bêta, le type FILE vous permet de stocker des références de fichiers et des métadonnées en tant que valeurs de colonne dans une table. Voir type FILE et données non structurées.
Exigences
- Un workspace Databricks avec Unity Catalog activé.
CREATE CATALOGprivilège sur le métastore. Consultez Créer des catalogues. Si vous ne pouvez pas créer de catalogue, demandez l'accès à votre administrateur ou utilisez un catalogue existant sur lequel vous disposez du privilègeCREATE SCHEMA.- Databricks Runtime 14.3 LTS et versions supérieures.
- Pour les fonctions IA : un Workspace dans une région prise en charge.
- Pour OpenSharing : privilèges
CREATE SHAREetCREATE RECIPIENTsur le métastore. Voir Partager des données et des assets d'IA en toute sécurité.
Étape 1 : créer un volume
Créez un catalogue, un schéma et un volume pour stocker vos fichiers. Pour des instructions détaillées sur la gestion des volumes, consultez Créez et gérez des volumes Unity Catalog.
Étape 1.1 : Créez un catalogue et un schéma
- SQL
- Python
- Catalog Explorer
-- Create a catalog
CREATE CATALOG IF NOT EXISTS unstructured_data_lab;
USE CATALOG unstructured_data_lab;
-- Create a schema
CREATE SCHEMA IF NOT EXISTS raw;
USE SCHEMA raw;
spark.sql("CREATE CATALOG IF NOT EXISTS unstructured_data_lab")
spark.sql("USE CATALOG unstructured_data_lab")
spark.sql("CREATE SCHEMA IF NOT EXISTS raw")
spark.sql("USE SCHEMA raw")
- Cliquez sur
Catalogue dans la barre latérale.
- Cliquez sur Créer > Créer un catalogue .
- Entrez unstructured_data_lab comme nom du catalogue .
- Cliquez sur Créer .
- Cliquez sur **Afficher le catalogue**.
Sur la page du catalogue :
- Cliquez sur Créer un schéma .
- Saisissez raw comme nom de schéma .
- Cliquez sur Créer .
Étape 1.2 : créer un volume géré
- SQL
- Python
- Catalog Explorer
CREATE VOLUME IF NOT EXISTS files_volume
COMMENT 'Volume for storing unstructured data files';
spark.sql("""
CREATE VOLUME IF NOT EXISTS files_volume
COMMENT 'Volume for storing unstructured data files'
""")
Sur la page du schéma :
- Cliquez sur Créer > Volume .
- Saisissez files_volume comme nom de volume .
- Vérifiez que Managed volume est sélectionné.
- Cliquez sur Créer .
Étape 2 : upload files
upload les fichiers vers votre volume. Pour des exemples complets de gestion de fichiers, consultez Travailler avec des fichiers dans les volumes Unity Catalog.
Étape 2.1 : upload files
Vous pouvez utiliser des exemples de databricks-datasets pour ce tutoriel, ou upload vos propres fichiers à l'aide de l'interface utilisateur de Catalog Explorer.
Vous pouvez utiliser les commandes Python pour copier des fichiers de databricks-datasets vers votre volume même si vous n'êtes pas familier avec Python. Consultez Gérer les notebooks Databricks pour obtenir des instructions sur l'exécution de commandes dans les notebooks.
- Python
- Catalog Explorer
# Upload a single image file
dbutils.fs.cp(
"dbfs:/databricks-datasets/flower_photos/roses/10090824183_d02c613f10_m.jpg",
"/Volumes/unstructured_data_lab/raw/files_volume/rose.jpg"
)
# Upload a single PDF file
dbutils.fs.cp(
"dbfs:/databricks-datasets/COVID/CORD-19/2020-03-13/COVID.DATA.LIC.AGMT.pdf",
"/Volumes/unstructured_data_lab/raw/files_volume/covid.pdf"
)
# Upload a directory
local_dir = "dbfs:/databricks-datasets/samples/data/mllib"
volume_path = "/Volumes/unstructured_data_lab/raw/files_volume/sample_files"
for file_info in dbutils.fs.ls(local_dir):
source = file_info.path
dest = f"{volume_path}/{file_info.name}"
dbutils.fs.cp(source, dest, recurse=True)
print(f"Uploaded: {file_info.name}")
Le code Python dans l'onglet Python upload deux fichiers (un JPG et un PDF) et un répertoire qui inclut les fichiers .txt et .csv. Pour upload des fichiers à l'aide de l'Explorateur de catalogues :
- Depuis la page du volume, cliquez sur **upload** vers ce volume.
- Dans la boîte de dialogue Upload files , sous Fichiers , cliquez sur Parcourir ou glissez-déposez des fichiers dans la zone de dépôt.
- Sous Volume de destination , vérifiez que le volume que vous avez créé à l’étape précédente est sélectionné.
Étape 2.2 : Vérifier l'upload
- SQL
- Python
- Catalog Explorer
LIST '/Volumes/unstructured_data_lab/raw/files_volume/';
files = dbutils.fs.ls("/Volumes/unstructured_data_lab/raw/files_volume/")
for f in files:
print(f"{f.name}\t{f.size} bytes")
Lorsque les fichiers sont téléchargés, ils apparaissent sur la page du volume. Cliquez sur un nom de fichier pour afficher un aperçu, ou cliquez sur un répertoire pour afficher les fichiers individuels.
Alternative : utilisez la commande magique %fs
Utilisez la commande magique %fs :
%fs ls /Volumes/unstructured_data_lab/raw/files_volume/
Étape 3 : Interroger les métadonnées du fichier
Interroger les informations de fichier pour comprendre le contenu de votre volume. Pour plus de modèles de query, voir Lister et interroger des fichiers dans des volumes avec SQL.
Étape 3.1 : Afficher les métadonnées du fichier
- SQL
- Python
- Catalog Explorer
SELECT
path,
_metadata.file_name,
_metadata.file_size,
_metadata.file_modification_time
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile'
);
df = (
spark.read
.format("binaryFile")
.option("recursiveFileLookup", "true")
.load("/Volumes/unstructured_data_lab/raw/files_volume/")
)
df.select("path", "modificationTime", "length").show(truncate=False)
La page du volume dans l'Explorateur de catalogue affiche le Nom (y compris l'extension), la Taille et la date de Dernière modification de chaque fichier.
Étape 4 : Query et traiter les fichiers
Utilisez les fonctions Databricks AI pour extraire du contenu des documents et analyser les images. Pour une vue d'ensemble complète des capacités des AI Functions, consultez Enrichir des données à l'aide des AI Functions.
Les fonctions d'IA nécessitent un Workspace dans une région prise en charge. Consultez Enrichir des données à l'aide des AI Functions.
Si vous n'avez pas accès aux fonctions d'IA, utilisez plutôt les bibliothèques Python standard. Développez les sections alternatives ci-dessous pour des exemples.
Étape 4.1 : Analyser des documents
- SQL
- Python
SELECT
path AS file_path,
ai_parse_document(content, map('version', '2.0')) AS parsed_content
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.pdf'
);
result_df = spark.sql("""
SELECT
path AS file_path,
ai_parse_document(content, map('version', '2.0')) AS parsed_content
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.pdf'
)
""")
display(result_df)
Autre option : analyser des PDF sans fonctions IA
Si les fonctions d'IA ne sont pas disponibles dans votre région, utilisez les bibliothèques Python :
%pip install PyPDF2==3.0.1
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
from PyPDF2 import PdfReader
import io
@udf(returnType=StringType())
def extract_pdf_text(content):
if content is None:
return None
try:
reader = PdfReader(io.BytesIO(content))
return "\n".join(page.extract_text() or "" for page in reader.pages)
except Exception as e:
return f"Error: {str(e)}"
df = spark.read.format("binaryFile") \
.option("pathGlobFilter", "*.pdf") \
.load("/Volumes/unstructured_data_lab/raw/files_volume/")
result_df = df.withColumn("text_content", extract_pdf_text("content"))
display(result_df.select("path", "text_content"))
Étape 4.2 : Analyser les images
- SQL
- Python
SELECT
path,
ai_query(
'databricks-llama-4-maverick',
'Describe this image in one sentence:',
files => content
) AS description
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.{jpg,jpeg,png}'
)
WHERE _metadata.file_size < 5000000;
result_df = spark.sql("""
SELECT
path,
ai_query(
'databricks-llama-4-maverick',
'Describe this image in one sentence:',
files => content
) AS description
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.{jpg,jpeg,png}'
)
WHERE _metadata.file_size < 5000000
""")
display(result_df)
Alternative : Extraire les métadonnées d'image sans fonctions d'IA
Extraire les métadonnées d'image sans fonctions IA.
%pip install pillow==10.4.0
from pyspark.sql.functions import udf
from pyspark.sql.types import StructType, StructField, IntegerType, StringType
from PIL import Image
import io
image_schema = StructType([
StructField("width", IntegerType()),
StructField("height", IntegerType()),
StructField("format", StringType())
])
@udf(returnType=image_schema)
def get_image_info(content):
if content is None:
return None
try:
img = Image.open(io.BytesIO(content))
return {"width": img.width, "height": img.height, "format": img.format}
except:
return None
df = spark.read.format("binaryFile") \
.option("pathGlobFilter", "*.{jpg,jpeg,png}") \
.load("/Volumes/unstructured_data_lab/raw/files_volume/")
result_df = df.withColumn("image_info", get_image_info("content"))
display(result_df.select("path", "image_info.*"))
Étape 4,3 : filtrer et analyser par nom de fichier
Cet exemple filtre les fichiers image contenant la sous-chaîne « rose » dans leur nom de fichier.
- SQL
- Python
SELECT
path AS file_path,
ai_query(
'databricks-llama-4-maverick',
'Describe this image in one sentence:',
files => content
) AS description
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.{jpg,jpeg,png}'
)
WHERE _metadata.file_name ILIKE '%rose%';
result_df = spark.sql("""
SELECT
path AS file_path,
ai_query(
'databricks-llama-4-maverick',
'Describe this image in one sentence:',
files => content
) AS description
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile',
fileNamePattern => '*.{jpg,jpeg,png}'
)
WHERE _metadata.file_name ILIKE '%rose%'
""")
display(result_df)
Étape 4.4 : joindre des fichiers avec des tables structurées
Cet exemple utilise des numéros de ligne pour associer des fichiers à des courses de taxi à des fins de démonstration. En production, effectuez une jointure sur des clés métier significatives.
- SQL
- Python
-- This example demonstrates joining file metadata with structured data
-- by pairing files with taxi trips using row numbers
WITH files_with_row AS (
SELECT
path,
SPLIT(path, '/')[SIZE(SPLIT(path, '/')) - 1] AS file_name,
length,
ROW_NUMBER() OVER (ORDER BY path) AS file_row
FROM read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/',
format => 'binaryFile'
)
),
trips_with_row AS (
SELECT
tpep_pickup_datetime,
pickup_zip,
dropoff_zip,
fare_amount,
ROW_NUMBER() OVER (ORDER BY tpep_pickup_datetime) AS trip_row
FROM samples.nyctaxi.trips
WHERE pickup_zip IS NOT NULL
LIMIT 5
)
SELECT
f.path,
f.file_name,
f.length,
t.pickup_zip,
t.dropoff_zip,
t.fare_amount,
t.tpep_pickup_datetime
FROM files_with_row f
INNER JOIN trips_with_row t ON f.file_row = t.trip_row;
from pyspark.sql.functions import col, row_number, element_at, split
from pyspark.sql.window import Window
# Read files and add row numbers
files_df = spark.read.format("binaryFile") \
.load("/Volumes/unstructured_data_lab/raw/files_volume/") \
.withColumn("file_name", element_at(split(col("path"), "/"), -1))
files_with_row = files_df.alias("files") \
.withColumn("file_row", row_number().over(Window.orderBy("path")))
# Get trips and add row numbers
trips_df = spark.table("samples.nyctaxi.trips") \
.filter(col("pickup_zip").isNotNull()) \
.limit(5)
trips_with_row = trips_df.alias("trips") \
.withColumn("trip_row", row_number().over(Window.orderBy("tpep_pickup_datetime")))
# Join on row numbers
result_df = files_with_row \
.join(trips_with_row, col("file_row") == col("trip_row"), "inner") \
.select(
"files.path",
"files.file_name",
"files.length",
"trips.pickup_zip",
"trips.dropoff_zip",
"trips.fare_amount",
"trips.tpep_pickup_datetime"
)
display(result_df)
Étape 5 : appliquer le contrôle d'accès
Contrôlez qui peut lire et écrire des fichiers dans vos volumes. Pour en savoir plus sur la gestion des privilèges dans Unity Catalog, consultez Gérer les privilèges dans Unity Catalog.
Étape 5.1 : Accorder l'accès
- SQL
- Python
- Catalog Explorer
-- Replace <user-or-group-name> with your workspace group or user name
-- Grant read access
GRANT READ VOLUME ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`;
-- Grant read and write access
GRANT READ VOLUME, WRITE VOLUME ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`;
-- Grant all privileges
GRANT ALL PRIVILEGES ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`;
# Replace <user-or-group-name> with your workspace group or user name
spark.sql("""
GRANT READ VOLUME ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`
""")
spark.sql("""
GRANT READ VOLUME, WRITE VOLUME ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`
""")
spark.sql("""
GRANT ALL PRIVILEGES ON VOLUME unstructured_data_lab.raw.files_volume
TO `<user-or-group-name>`
""")
- Accédez à l'onglet **Permissions** de la page du volume.
- Cliquez sur Accorder .
- Saisissez l'adresse e-mail d'un utilisateur ou le nom d'un groupe.
- Sélectionnez les autorisations à accorder.
- Cliquez sur Confirmer .
Étape 5.2 : afficher les privilèges actuels
- SQL
- Python
- Catalog Explorer
SHOW GRANTS ON VOLUME unstructured_data_lab.raw.files_volume;
display(spark.sql("SHOW GRANTS ON VOLUME unstructured_data_lab.raw.files_volume"))
Le Permissions tab de la page du volume indique quels utilisateurs et groupes ont accès au volume.
Étape 6 : Configurer l'ingestion incrémentielle
Utilisez Auto Loader pour traiter automatiquement les nouveaux fichiers à mesure qu'ils arrivent dans votre volume. Ce modèle est utile pour les workflows d'ingestion de données continues. Pour plus de modèles d'ingestion, voir Modèles courants de chargement des données.
Étape 6.1 : créer une table de streaming
- SQL
- Python
CREATE OR REFRESH STREAMING TABLE document_ingestion
SCHEDULE EVERY 1 HOUR
AS SELECT
path,
modificationTime,
length,
content,
_metadata,
current_timestamp() AS ingestion_time
FROM STREAM(read_files(
'/Volumes/unstructured_data_lab/raw/files_volume/incoming/',
format => 'binaryFile'
));
from pyspark.sql.functions import current_timestamp, col
dbutils.fs.mkdirs("/Volumes/unstructured_data_lab/raw/files_volume/incoming/")
df = spark.readStream.format("cloudFiles") \
.option("cloudFiles.format", "binaryFile") \
.option("pathGlobFilter", "*.pdf") \
.load("/Volumes/unstructured_data_lab/raw/files_volume/incoming/")
df_enriched = df \
.withColumn("ingestion_time", current_timestamp()) \
.withColumn("source_file", col("_metadata.file_path"))
query = df_enriched.writeStream \
.option("checkpointLocation",
"/Volumes/unstructured_data_lab/raw/files_volume/_checkpoints/docs") \
.trigger(availableNow=True) \
.toTable("document_ingestion")
query.awaitTermination()
Étape 7 : Partager des fichiers avec OpenSharing
Partagez des volumes en toute sécurité avec des utilisateurs d'autres organisations en utilisant OpenSharing. Vous devez créer un destinataire avant de partager. Un destinataire représente une organisation externe ou un utilisateur qui peut accéder à vos données partagées. Consultez Créer des destinataires de données pour OpenSharing (partage Databricks-to-Databricks) pour la configuration du destinataire.
Étape 7.1 : Créer et configurer un partage
- SQL
- Python
-- Create a share
CREATE SHARE IF NOT EXISTS unstructured_data_share
COMMENT 'Document files for partners';
-- Add the volume
ALTER SHARE unstructured_data_share
ADD VOLUME unstructured_data_lab.raw.files_volume;
-- Create a recipient
CREATE RECIPIENT IF NOT EXISTS <partner_org>
USING ID '<recipient-sharing-identifier>';
-- Grant access
GRANT SELECT ON SHARE unstructured_data_share
TO RECIPIENT <partner_org>;
spark.sql("""
CREATE SHARE IF NOT EXISTS unstructured_data_share
COMMENT 'Document files for partners'
""")
spark.sql("""
ALTER SHARE unstructured_data_share
ADD VOLUME unstructured_data_lab.raw.files_volume
""")
spark.sql("""
CREATE RECIPIENT IF NOT EXISTS <partner_org>
USING ID '<recipient-sharing-identifier>'
""")
spark.sql("""
GRANT SELECT ON SHARE unstructured_data_share
TO RECIPIENT <partner_org>
""")
Étape 7.2 : Accédez aux données partagées (en tant que destinataire)
- SQL
- Python
-- View available shares
SHOW SHARES IN PROVIDER <provider_name>;
-- Create a catalog from the share
CREATE CATALOG IF NOT EXISTS shared_documents
FROM SHARE <provider_name>.unstructured_data_share;
-- Query shared files
SELECT * EXCEPT (content), _metadata
FROM read_files(
'/Volumes/shared_documents/raw/files_volume/',
format => 'binaryFile'
)
LIMIT 10;
spark.sql("SHOW SHARES IN PROVIDER <provider_name>").show()
spark.sql("""
CREATE CATALOG IF NOT EXISTS shared_documents
FROM SHARE <provider_name>.unstructured_data_share
""")
df = spark.read.format("binaryFile") \
.load("/Volumes/shared_documents/raw/files_volume/")
df.select("path", "modificationTime", "length").show(10)
Étape 8 : Nettoyer les fichiers
Supprimez les fichiers lorsqu’ils ne sont plus nécessaires.
- Python
- CLI
# Delete a single file
dbutils.fs.rm("/Volumes/unstructured_data_lab/raw/files_volume/covid.pdf")
# Delete a directory recursively
dbutils.fs.rm("/Volumes/unstructured_data_lab/raw/files_volume/sample_files/", recurse=True)
# Delete a single file
databricks fs rm dbfs:/Volumes/unstructured_data_lab/raw/files_volume/covid.pdf
# Delete a directory recursively
databricks fs rm -r dbfs:/Volumes/unstructured_data_lab/raw/files_volume/sample_files/
Alternative : utilisez Python standard
import os
os.remove("/Volumes/unstructured_data_lab/raw/files_volume/covid.pdf")
import shutil
shutil.rmtree("/Volumes/unstructured_data_lab/raw/files_volume/sample_files/")
Ressources supplémentaires
Continuer à en apprendre davantage sur les volumes
- Que sont les volumes Unity Catalog ?
- Travailler avec les fichiers dans les volumes Unity Catalog
- Créez et gérez les volumes Unity Catalog
Explorer les capacités associées
- Enrichir des données avec les AI Functions
- Modèles courants de chargement de données
- Partager les assets de données et d'IA en toute sécurité