Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Důležité
Tato funkce je ve verzi Public Preview.
VARIANT je částečně strukturovaný datový typ, který ukládá data podobná formátu JSON v binárním formátu, který popisuje sama sebe. Datový VARIANT typ je k dispozici v Databricks Runtime 15.3 a vyšší.
Azure Databricks doporučuje pro polostrukturovaná data používat VARIANT namísto řetězců JSON. Pro uživatele, kteří aktuálně používají řetězce JSON a chtějí migrovat, viz Jak se varianta liší od řetězců JSON?.
Pokud chcete dotazovat částečně strukturovaná data uložená jako řetězce JSON, přečtěte si téma Dotazování řetězců JSON.
Poznámka:
VARIANT sloupce nelze použít pro clusteringové klíče, oddíly nebo Z-řádové klíče. Datový typ VARIANT nelze použít pro porovnání, seskupování, řazení a operace nastavení. Úplný seznam omezení najdete v tématu Omezení.
Vytvoření tabulky s variantovým sloupcem
Pokud chcete vytvořit sloupec varianty, použijte parse_json funkci (SQL nebo Python).
Spuštěním následujícího příkazu vytvořte tabulku s vysoce vnořenými daty uloženými jako VARIANT. (Tato data se používají v jiných příkladech na této stránce.)
Python
# Create a table with a variant column
store_data='''
{
"store":{
"fruit":[
{"weight":8,"type":"apple"},
{"weight":9,"type":"pear"}
],
"basket":[
[1,2,{"b":"y","a":"x"}],
[3,4],
[5,6]
],
"book":[
{
"author":"Nigel Rees",
"title":"Sayings of the Century",
"category":"reference",
"price":8.95
},
{
"author":"Herman Melville",
"title":"Moby Dick",
"category":"fiction",
"price":8.99,
"isbn":"0-553-21311-3"
},
{
"author":"J. R. R. Tolkien",
"title":"The Lord of the Rings",
"category":"fiction",
"reader":[
{"age":25,"name":"bob"},
{"age":26,"name":"jack"}
],
"price":22.99,
"isbn":"0-395-19395-8"
}
],
"bicycle":{
"price":19.95,
"color":"red"
}
},
"owner":"amy",
"zip code":"94025",
"fb:testid":"1234"
}
'''
# Create a DataFrame
df = spark.createDataFrame([(store_data,)], ["json"])
# Convert to a variant
df_variant = df.select(parse_json(col("json")).alias("raw"))
# Alternatively, create the DataFrame directly
# df_variant = spark.range(1).select(parse_json(lit(store_data)))
df_variant.display()
# Write out as a table
df_variant.write.saveAsTable("store_data")
SQL
-- Create a table with a variant column
CREATE TABLE store_data AS
SELECT parse_json(
'{
"store":{
"fruit": [
{"weight":8,"type":"apple"},
{"weight":9,"type":"pear"}
],
"basket":[
[1,2,{"b":"y","a":"x"}],
[3,4],
[5,6]
],
"book":[
{
"author":"Nigel Rees",
"title":"Sayings of the Century",
"category":"reference",
"price":8.95
},
{
"author":"Herman Melville",
"title":"Moby Dick",
"category":"fiction",
"price":8.99,
"isbn":"0-553-21311-3"
},
{
"author":"J. R. R. Tolkien",
"title":"The Lord of the Rings",
"category":"fiction",
"reader":[
{"age":25,"name":"bob"},
{"age":26,"name":"jack"}
],
"price":22.99,
"isbn":"0-395-19395-8"
}
],
"bicycle":{
"price":19.95,
"color":"red"
}
},
"owner":"amy",
"zip code":"94025",
"fb:testid":"1234"
}'
) as raw
SELECT * FROM store_data
Dotazování polí ve variantním sloupci
Pokud chcete extrahovat pole z variantního sloupce, použijte variant_get funkci (SQL nebo Python) a zadejte název pole JSON v cestě extrakce. V názvech polí se vždy rozlišují malá a velká písmena.
Python
# Extract a top-level field
df_variant.select(variant_get(col("raw"), "$.owner", "string")).display()
SQL
-- Extract a top-level field
SELECT variant_get(store_data.raw, '$.owner') AS owner FROM store_data
Syntaxi SQL můžete také použít k dotazování polí ve sloupci varianty. Viz zkratka SQL pro variant_get.
Zkratka SQL pro variant_get
Syntaxe SQL pro dotazování řetězců JSON a dalších složitých datových typů v Azure Databricks se vztahuje na VARIANT data, včetně následujících:
- Slouží
:k výběru polí nejvyšší úrovně. - Použijte
.nebo[<key>]k výběru vnořených polí s pojmenovanými klíči. - Slouží
[<index>]k výběru hodnot z polí.
SELECT raw:owner FROM store_data
+-------+
| owner |
+-------+
| "amy" |
+-------+
-- Enclose a field name that contains special characters in single quotes inside square brackets.
SELECT raw:['zip code'], raw:['fb:testid'] FROM store_data
+----------+-----------+
| zip code | fb:testid |
+----------+-----------+
| "94025" | "1234" |
+----------+-----------+
Syntaxe ['<field>'] umožňuje escapovat libovolný speciální znak v názvu pole, včetně mezer, teček (.), dvojteček (:) a hranatých závorek ([ ]). Azure Databricks doporučuje tuto syntaxi pro každý název pole, který obsahuje speciální znak. Slouží raw:['zip.code'] například k výběru pole s názvem zip.codenebo raw:['A[1]'] k výběru pole s názvem A[1].
Backticks také escapují názvy polí, které obsahují mezery nebo dvojtečky, ale neescapují tečky ani hranaté závorky. Název pole, který obsahuje tečku nebo hranaté závorky, vrací při použití zpětných apostrofů pro escapování hodnotu NULL, proto pro takové názvy použijte syntaxi ['<field>'].
Chcete-li extrahovat pole, která obsahují speciální znaky v PySpark, použijte stejnou syntaxi závorek v variant_get cestě extrakce:
# Escape special characters in the extraction path
df_variant.select(variant_get(col("raw"), "$['zip.code']", "string"))
df_variant.select(variant_get(col("raw"), "$['A[1]']", "string"))
Extrahování vnořených polí variantních
Pokud chcete extrahovat vnořená pole ze sloupce varianty, zadejte je pomocí zápisu tečky nebo závorek. V názvech polí se vždy rozlišují malá a velká písmena.
Python
# Use dot notation
df_variant.select(variant_get(col("raw"), "$.store.bicycle", "string")).display()
# Use brackets
df_variant.select(variant_get(col("raw"), "$.store['bicycle']", "string")).display()
Pokud nelze najít cestu, je null výsledek typu VariantVal.
SQL
-- Use dot notation
SELECT raw:store.bicycle FROM store_data
-- Use brackets
SELECT raw:store['bicycle'] FROM store_data
Pokud nelze najít cestu, je NULL výsledek typu VARIANT.
+-----------------+
| bicycle |
+-----------------+
| { |
| "color":"red", |
| "price":19.95 |
| } |
+-----------------+
Extrahování hodnot z variantových polí
Chcete-li extrahovat prvky z polí, indexujte s hranatými závorkami. Indexy jsou založené na 0.
Python
# Index elements
df_variant.select((variant_get(col("raw"), "$.store.fruit[0]", "string")),(variant_get(col("raw"), "$.store.fruit[1]", "string"))).display()
SQL
-- Index elements
SELECT raw:store.fruit[0], raw:store.fruit[1] FROM store_data
+-------------------+------------------+
| fruit | fruit |
+-------------------+------------------+
| { | { |
| "type":"apple", | "type":"pear", |
| "weight":8 | "weight":9 |
| } | } |
+-------------------+------------------+
Pokud cestu nelze najít nebo pokud je index pole mimo hranice, je výsledek null.
Práce s variantami v Pythonu
Varianty z datových rámců Sparku můžete extrahovat do Pythonu jako VariantVal a pracovat s nimi jednotlivě pomocí metod toPython a toJson.
# toPython
data = [
('{"name": "Alice", "age": 25}',),
('["person", "electronic"]',),
('1',)
]
df_person = spark.createDataFrame(data, ["json"])
# Collect variants into a VariantVal
variants = df_person.select(parse_json(col("json")).alias("v")).collect()
Výstup VariantVal jako řetězec JSON:
print(variants[0].v.toJson())
{"age":25,"name":"Alice"}
Převeďte VariantVal na objekt v Pythonu:
# First element is a dictionary
print(variants[0].v.toPython()["age"])
25
# Second element is a List
print(variants[1].v.toPython()[1])
electronic
# Third element is an Integer
print(variants[2].v.toPython())
1
Můžete také vytvořit VariantVal pomocí VariantVal.parseJson funkce.
# parseJson to construct VariantVal's in Python
from pyspark.sql.types import VariantVal
variant = VariantVal.parseJson('{"a": 1}')
Vytiskněte variantu jako řetězec JSON:
print(variant.toJson())
{"a":1}
Převeďte variantu na objekt Pythonu a vytiskněte hodnotu:
print(variant.toPython()["a"])
1
Vrácení schématu varianty
Pokud chcete vrátit schéma varianty, použijte schema_of_variant funkci (SQL nebo Python).
Python
# Return the schema of the variant
df_variant.select(schema_of_variant(col("raw"))).display()
SQL
-- Return the schema of the variant
SELECT schema_of_variant(raw) FROM store_data;
Pokud chcete vrátit kombinovaná schémata všech variant ve skupině, použijte schema_of_variant_agg funkci (SQL nebo Python).
Následující příklady vrátí schéma a potom kombinované schéma pro ukázková data json_data.
Python
json_data = [
('{"name": "Alice", "age": 25}',),
('{"id": 101, "department": "HR"}',),
('{"product": "Laptop", "price": 1200.50, "in_stock": true}',)
]
df_item = spark.createDataFrame(json_data, ["json"])
# Return the schema
df_item.select(parse_json(col("json")).alias("v")).select(schema_of_variant(col("v"))).display()
SQL
CREATE OR REPLACE TEMP VIEW json_data AS
SELECT '{"name": "Alice", "age": 25}' AS json UNION ALL
SELECT '{"id": 101, "department": "HR"}' UNION ALL
SELECT '{"product": "Laptop", "price": 1200.50, "in_stock": true}';
-- Return the schema
SELECT schema_of_variant(parse_json(json)) FROM json_data;
+-----------------------------------------------------------------+
| schema_of_variant(v) |
+-----------------------------------------------------------------+
| OBJECT<age: BIGINT, name: STRING> |
| OBJECT<department: STRING, id: BIGINT> |
| OBJECT<in_stock: BOOLEAN, price: DECIMAL(5,1), product: STRING> |
+-----------------------------------------------------------------+
Python
# Return the combined schema
df.select(parse_json(col("json")).alias("v")).select(schema_of_variant_agg(col("v"))).display()
SQL
-- Return the combined schema
SELECT schema_of_variant_agg(parse_json(json)) FROM json_data;
+----------------------------------------------------------------------------------------------------------------------------+
| schema_of_variant(v) |
+----------------------------------------------------------------------------------------------------------------------------+
| OBJECT<age: BIGINT, department: STRING, id: BIGINT, in_stock: BOOLEAN, name: STRING, price: DECIMAL(5,1), product: STRING> |
+----------------------------------------------------------------------------------------------------------------------------+
Zploštěné objekty a pole variant
Funkci generátoru variant_explode s hodnotami tabulky (SQL nebo Python) lze použít k zploštění variantových polí a objektů.
Python
Pomocí rozhraní API datového rámce TVF (table-valued function) můžete rozšířit variantu na více řádků:
spark.tvf.variant_explode(parse_json(lit(store_data))).display()
# To explode a nested field, first create a DataFrame with just the field
df_store_col = df_variant.select(variant_get(col("raw"), "$.store", "variant").alias("store"))
# Perform the explode with a lateral join and the outer function to return the new exploded DataFrame
df_store_exploded_lj = df_store_col.lateralJoin(spark.tvf.variant_explode(col("store").outer()))
df_store_exploded = df_store_exploded_lj.drop("store")
df_store_exploded.display()
SQL
Protože variant_explode je funkce generátoru, použijete ji jako součást FROM klauzule, nikoli v SELECT seznamu, jako v následujících příkladech:
SELECT key, value
FROM store_data,
LATERAL variant_explode(store_data.raw);
SELECT pos, value
FROM store_data,
LATERAL variant_explode(store_data.raw:store.basket[0]);
Pravidla přetypování variantního typu
Pole a skaláry můžete ukládat pomocí VARIANT typu. Při pokusu o přetypování variantních typů na jiné typy platí normální pravidla přetypování pro jednotlivé hodnoty a pole s následujícími dalšími pravidly.
Poznámka:
variant_get a try_variant_get přijímají typové argumenty a řídí se těmito pravidly přetypování.
| Typ zdroje | Chování |
|---|---|
VOID |
Výsledek je NULL typu VARIANT. |
ARRAY<elementType> |
elementType musí být typ, na který lze přetypovat VARIANT. |
Pokud existují konfliktní typy, které nelze vyřešit, při odvození typu pomocí schema_of_variant nebo schema_of_variant_agg funkce spadne zpět na VARIANT typ, místo STRING typu.
Python
try_variant_get K přetypování použijte funkci (Python):
# price is returned as a double, not a string
df_variant.select(try_variant_get(col("raw"), "$.store.bicycle.price", "double").alias("price"))
+------------------+
| price |
+------------------+
| 19.95 |
+------------------+
SQL
try_variant_get K přetypování použijte funkci (SQL):
-- price is returned as a double, not a string
SELECT try_variant_get(raw, '$.store.bicycle.price', 'double') as price FROM store_data
+------------------+
| price |
+------------------+
| 19.95 |
+------------------+
Můžete také použít :: nebo cast k přetypování hodnot na podporované datové typy:
-- cast into more complex types
SELECT cast(raw:store.bicycle AS STRUCT<price DOUBLE, color STRING>) bicycle FROM store_data;
-- `::` also supported
SELECT raw:store.bicycle::STRUCT<price DOUBLE, color STRING> bicycle FROM store_data;
+------------------+
| bicycle |
+------------------+
| { |
| "price":19.95, |
| "color":"red" |
| } |
+------------------+
Také použijte funkci try_variant_get (SQL nebo Python) k zpracování selhání přetypování.
Python
spark.range(1).select(parse_json(lit('{"a" : "c", "b" : 2}')).alias("v")).select(try_variant_get(col('v'), '$.a', 'boolean')).display()
SQL
SELECT try_variant_get(
parse_json('{"a" : "c", "b" : 2}'),
'$.a',
'boolean'
)
Variantní pravidla null
is_variant_null Pomocí funkce (SQL nebo Python) určete, jestli je hodnota varianty null.
Python
data = [
('null',),
(None,),
('{"field_a" : 1, "field_b" : 2}',)
]
df = spark.createDataFrame(data, ["null_data"])
df.select(parse_json(col("null_data")).alias("v")).select(is_variant_null(col("v"))).display()
+------------------+
|is_variant_null(v)|
+------------------+
| true|
+------------------+
| false|
+------------------+
| false|
+------------------+
SQL
Varianty můžou obsahovat dva druhy hodnot null:
-
SQL: SQL
NULLNULLindikátory naznačují, že hodnota chybí. Jsou to stejnéNULLjako při práci se strukturovanými daty. -
Varianta: Varianty
NULLNULLindikují, že varianta explicitně obsahujeNULLhodnotu. Nejedná se o stejné hodnoty jako sqlNULL, protožeNULLhodnota je uložená v datech.
SELECT
is_variant_null(parse_json(NULL)) AS sql_null,
is_variant_null(parse_json('null')) AS variant_null,
is_variant_null(parse_json('{ "field_a": null }'):field_a) AS variant_null_value,
is_variant_null(parse_json('{ "field_a": null }'):missing) AS missing_sql_value_null
+--------+------------+------------------+----------------------+
|sql_null|variant_null|variant_null_value|missing_sql_value_null|
+--------+------------+------------------+----------------------+
| false| true| true| false|
+--------+------------+------------------+----------------------+
Dodatečné zdroje
-
Jak se typ variant liší od řetězců JSON?: Srovnání
VARIANTa řetězců JSON, včetně pokynů k migraci pro uživatele, kteří přecházejí z ukládání řetězců JSON. -
Podpora typů variant pro Apache Iceberg a Delta Lake: Úplný seznam
VARIANTomezení a chování specifické pro Delta.