2017-09-21 4 views
0

Je l'objet JSON suivant pour la présence d'une personne à des conférences:Amazon Athena - Questions Nested JSON

{"conferences_attended": [ 
      {"conference_name": "dreamforce", 
      "date": "2017", 
      "city": "san francisco", 
      "state": "ca"}, 
      {"conference_name": "RampUp", 
      "date": "2016", 
      "city": "san francisco", 
      "state": "ca"}, 
      ], 
    "last_name" : "doe"} 

J'ai couru le code suivant pour créer la table pointant vers où j'ai les données stockées dans s3

CREATE EXTERNAL TABLE IF NOT EXISTS my_db.attendees (
     `last_name` string, 
     `conferences_attended` array< struct< 
      conference_name:string, 
      date:string, 
      city:string, 
      state:string, 
     >>, 
    ) 
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
    WITH SERDEPROPERTIES (
     'serialization.format' = '1' 
    ) LOCATION 's3://**' 
    TBLPROPERTIES ('has_encrypted_data'='false'); 

maintenant, je compose de 2 parties à ma question.

1) Comment interroger pour accéder aux données contenues dans un objet json imbriqué? Les deux requêtes ci-dessous ne fonctionnent pas et pas beaucoup d'autres similaires.

SELECT conferences_attended 
    FROM attendees; 

    SELECT conferences_attended.conference_name 
    FROM attendees; 

2) Comment puis-je demander des résultats qui ne correspondent qu'à une portion spécifique du json imbriqué?

SELECT * 
    FROM attendees 
    WHERE conferences_attended.conference_name like '%force%'; 

Je reçois des erreurs qui me porte à croire que je dois changer les types de données ou non imbriquer les données ou quelque chose similr ... Merci pour l'aide et des liens vers des informations soutenant ces types d'actions. Note, j'ai lu les liens suivants et je les ai trouvés utiles, mais je n'ai toujours pas résolu mes besoins. http://docs.aws.amazon.com/athena/latest/ug/rows-and-structs.html et http://thornydev.blogspot.com/2013/07/querying-json-records-via-hive.html et bien d'autres ...

Enfin, des conseils ou des ressources pour les différences entre « org.apache.hive.hcatalog.data.JsonSerDe » et « org.openx.data.jsonserde.JsonSerDe » sont les bienvenus .

Répondre

0

Tout d'abord, les champs de votre table externe ne sont pas en faisant correspondre les champs dans un fichier JSON auquel vous essayez de pointer.

Comme il semble, votre définition de la table devrait être comme suit:

CREATE EXTERNAL TABLE IF NOT EXISTS my_db.attendees (
    `last_name` string, 
    `conferences_attended` array<struct<conference_name:string, 
    date:string, city:string, state:string>>, 
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
WITH SERDEPROPERTIES (
    'serialization.format' = '1' 
) LOCATION 's3://**' 
TBLPROPERTIES ('has_encrypted_data'='false'); 

Vous avez mentionné company_name et linkedin_company_id comme des champs de conferences_attended pendant que vous essayez d'accéder à d'autres domaines.

Après cela, vous pouvez accéder aux champs de la manière suivante:

SELECT conferences_attended 
FROM attendees; 

Cependant, étant donné conferences_attended est un tableau de structures, vous devez index de tableau mention pour accéder aux champs de cette structure particulière du tableau . Ainsi, au lieu de cela:

SELECT conferences_attended.conference_name 
FROM attendees; 

Essayez quelque chose comme ceci:

SELECT conferences_attended[1].conference_name FROM attendees; 

Maintenant, si vous voulez analyser toutes les structures au sein de tableau et appliquer un filtre sur les données, vous pouvez le faire en utilisant le UNNEST fonction de la manière suivante:

SELECT 
last_name, 
conferences.conference_name, 
conferences.date, 
conferences.city, 
conferences.state 
FROM 
attendees CROSS JOIN UNNEST(conferences_attended) as t(conferences) 
WHERE 
conferences.conference_name like '%force%'; 

Vous pouvez consulter le lien suivant pour d'autres références: http://docs.aws.amazon.com/athena/latest/ug/flattening-arrays.html