Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Belangrijk
Deze functie is beschikbaar als openbare preview.
In dit artikel wordt beschreven hoe u semi-gestructureerde gegevens kunt opvragen en transformeren die zijn opgeslagen als VARIANT. Het VARIANT gegevenstype is beschikbaar in Databricks Runtime 15.3 en hoger.
Databricks raadt aan om JSON-tekenreeksen te gebruiken VARIANT . Zie Hoe verschilt de variant van JSON-tekenreeksen die momenteel worden gemigreerd voor gebruikers die JSON-tekenreeksen willen migreren.
Als u voorbeelden wilt zien voor het uitvoeren van query's op semi-gestructureerde gegevens die zijn opgeslagen met JSON-tekenreeksen, raadpleegt u Query-JSON-tekenreeksen.
Notitie
VARIANT kolommen kunnen niet worden gebruikt voor clustersleutels, partities of Z-ordersleutels. Het VARIANT gegevenstype kan niet worden gebruikt voor vergelijkingen, groepering, volgorde en setbewerkingen. Zie Beperkingenvoor een volledige lijst met beperkingen.
Een tabel met een variantkolom maken
Als u een variantkolom wilt maken, gebruikt u de parse_json functie (SQL of Python).
Voer het volgende uit om een tabel te maken met sterk geneste gegevens die zijn opgeslagen als VARIANT. (Deze gegevens worden gebruikt in andere voorbeelden op deze pagina.)
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
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")
Queryvelden in een variantkolom
Als u velden wilt extraheren uit een variantkolom, gebruikt u de variant_get functie (SQL of Python) die de naam van het JSON-veld in het extractiepad opgeeft. Veldnamen zijn altijd hoofdlettergevoelig.
SQL
-- Extract a top-level field
SELECT variant_get(store_data.raw, '$.owner') AS owner FROM store_data
U kunt ook SQL-syntaxis gebruiken om query's uit te voeren op velden in een variantkolom. Zie SQL-afkorting voor variant_get.
Python
# Extract a top-level field
df_variant.select(variant_get(col("raw"), "$.owner", "string")).display()
SQL-afkorting voor variant_get
De SQL-syntaxis voor het uitvoeren van query's op JSON-tekenreeksen en andere complexe gegevenstypen in Azure Databricks is van toepassing op VARIANT gegevens, waaronder:
- Gebruik
:om velden op het hoogste niveau te selecteren. - Gebruik
.of[<key>]om geneste velden met benoemde sleutels te selecteren. - Gebruik
[<index>]om waarden te selecteren in matrices.
SELECT raw:owner FROM store_data
+-------+
| owner |
+-------+
| "amy" |
+-------+
-- Use backticks to escape special characters.
SELECT raw:`zip code`, raw:`fb:testid` FROM store_data
+----------+-----------+
| zip code | fb:testid |
+----------+-----------+
| "94025" | "1234" |
+----------+-----------+
Als een veldnaam een punt. () bevat, moet u deze escapen met vierkante haken ([ ]). Met de volgende query selecteert u bijvoorbeeld een veld met de naam zip.code:
SELECT raw:['zip.code'] FROM store_data
Geneste variantvelden extraheren
Als u geneste velden uit een variantkolom wilt extraheren, geeft u deze op met puntnotatie of haakjes. Veldnamen zijn altijd hoofdlettergevoelig.
SQL
-- Use dot notation
SELECT raw:store.bicycle FROM store_data
-- Use brackets
SELECT raw:store['bicycle'] FROM store_data
Als een pad niet kan worden gevonden, is NULL het resultaat van het type VARIANT.
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()
Als een pad niet kan worden gevonden, is null het resultaat van het type VariantVal.
+-----------------+
| bicycle |
+-----------------+
| { |
| "color":"red", |
| "price":19.95 |
| } |
+-----------------+
Waarden extraheren uit variantmatrices
Als u elementen wilt extraheren uit matrices, indexeert u met vierkante haken. Indexen zijn gebaseerd op 0.
SQL
-- Index elements
SELECT raw:store.fruit[0], raw:store.fruit[1] FROM store_data
Python
# Index elements
df_variant.select((variant_get(col("raw"), "$.store.fruit[0]", "string")),(variant_get(col("raw"), "$.store.fruit[1]", "string"))).display()
+-------------------+------------------+
| fruit | fruit |
+-------------------+------------------+
| { | { |
| "type":"apple", | "type":"pear", |
| "weight":8 | "weight":9 |
| } | } |
+-------------------+------------------+
Als het pad niet kan worden gevonden of als de matrixindex buiten de grenzen valt, is het resultaat null.
Werken met varianten in Python
U kunt varianten uit Spark DataFrames als volgt extraheren in Python VariantVal en ermee werken met behulp van de toPython en toJson methoden.
# 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()
Geef de VariantVal weer als een JSON-tekenreeks:
print(variants[0].v.toJson())
{"age":25,"name":"Alice"}
Een VariantVal converteren naar een Python-object:
# 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
U kunt ook bouwen VariantVal met behulp van de VariantVal.parseJson functie.
# parseJson to construct VariantVal's in Python
from pyspark.sql.types import VariantVal
variant = VariantVal.parseJson('{"a": 1}')
De variant afdrukken als een JSON-tekenreeks:
print(variant.toJson())
{"a":1}
Converteer de variant naar een Python-object en druk een waarde af:
print(variant.toPython()["a"])
1
Het schema van een variant retourneren
Als u het schema van een variant wilt retourneren, gebruikt u de schema_of_variant functie (SQL of Python).
SQL
-- Return the schema of the variant
SELECT schema_of_variant(raw) FROM store_data;
Python
# Return the schema of the variant
df_variant.select(schema_of_variant(col("raw"))).display()
Als u de gecombineerde schema's van alle varianten in een groep wilt retourneren, gebruikt u de schema_of_variant_agg functie (SQL of Python).
De volgende voorbeelden retourneren het schema en vervolgens het gecombineerde schema voor de voorbeeldgegevens json_data.
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;
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()
+-----------------------------------------------------------------+
| schema_of_variant(v) |
+-----------------------------------------------------------------+
| OBJECT<age: BIGINT, name: STRING> |
| OBJECT<department: STRING, id: BIGINT> |
| OBJECT<in_stock: BOOLEAN, price: DECIMAL(5,1), product: STRING> |
+-----------------------------------------------------------------+
SQL
-- Return the combined schema
SELECT schema_of_variant_agg(parse_json(json)) FROM json_data;
Python
# Return the combined schema
df.select(parse_json(col("json")).alias("v")).select(schema_of_variant_agg(col("v"))).display()
+----------------------------------------------------------------------------------------------------------------------------+
| schema_of_variant(v) |
+----------------------------------------------------------------------------------------------------------------------------+
| OBJECT<age: BIGINT, department: STRING, id: BIGINT, in_stock: BOOLEAN, name: STRING, price: DECIMAL(5,1), product: STRING> |
+----------------------------------------------------------------------------------------------------------------------------+
Afgevlakte variantobjecten en matrices
De variant_explode generatorfunctie met tabelwaarde (SQL of Python) kan worden gebruikt voor het platmaken van variantmatrices en objecten.
SQL
Omdat variant_explode een generatorfunctie is, gebruikt u deze als onderdeel van de FROM component in plaats van in de SELECT lijst, zoals in de volgende voorbeelden:
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]);
Python
Gebruik de DataFrame API voor functies met tabelwaarden (TVF) om een variant uit te breiden naar meerdere rijen:
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()
Cast-regels voor varianttypen
U kunt matrices en scalaire waarden opslaan met behulp van VARIANT het type. Wanneer u varianttypen probeert te casten naar andere typen, zijn normale cast-regels van toepassing op afzonderlijke waarden en velden, met de volgende aanvullende regels.
Notitie
variant_get en try_variant_get neem de typeargumenten en volg deze cast-regels.
| Brontype | Gedrag |
|---|---|
VOID |
Het resultaat is een van het NULL type VARIANT. |
ARRAY<elementType> |
Het elementType moet een type zijn dat kan worden gecast naar VARIANT. |
Wanneer u het type afleidt met schema_of_variant of schema_of_variant_agg, vallen functies terug op VARIANT type in plaats van STRING type wanneer er conflicterende typen aanwezig zijn die niet kunnen worden opgelost.
SQL
Gebruik de try_variant_get functie (SQL) om het volgende te casten:
-- 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 |
+------------------+
U kunt ook :: of cast gebruiken om waarden naar ondersteunde gegevenstypen te casten.
-- 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" |
| } |
+------------------+
Python
Gebruik de try_variant_get functie (Python) om het volgende te casten:
# 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 |
+------------------+
Gebruik ook de try_variant_get functie (SQL of Python) voor het afhandelen van cast-fouten:
SQL
SELECT try_variant_get(
parse_json('{"a" : "c", "b" : 2}'),
'$.a',
'boolean'
)
Python
spark.range(1).select(parse_json(lit('{"a" : "c", "b" : 2}')).alias("v")).select(try_variant_get(col('v'), '$.a', 'boolean')).display()
Null-regels voor varianten
Gebruik de is_variant_null functie (SQL of Python) om te bepalen of de variantwaarde een variant null is.
SQL
Varianten kunnen twee soorten null-waarden bevatten:
-
SQL
NULL: SQLNULLs geven aan dat de waarde ontbreekt. Dit zijn dezelfdeNULLals bij het omgaan met gestructureerde gegevens. -
Variant: Variant
NULLNULLs geven aan dat de variant expliciet eenNULLwaarde bevat. Deze zijn niet hetzelfde als SQLNULLs, omdat deNULLwaarde wordt opgeslagen in de gegevens.
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|
+--------+------------+------------------+----------------------+
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|
+------------------+