O Problema
Vou tentar um novo acrônimo aqui - B2G - Business To GIS - significando a entrega de dados gerenciados externamente para o ArcGIS. É muito comum que sistemas externos ("business") ofereçam uma REST API que você pode chamar para obter dados em formato comum como JSON, mas também é muito comum que o servidor entregue um conjunto de dados em múltiplos pedaços (ou seja, "páginas"), e que o JSON não esteja em um dialeto bem definido como GeoJSON - você precisa analisá-lo em colunas, potencialmente a partir de objetos struct ou array.
Este post é sobre conquistar os dois desafios da paginação e análise, sem codificação, usando ArcGIS Data Interoperability.
Meus dados de assunto são dados de reclamações de clientes da Federal Communications Commission sobre chamadas indesejadas, filtrados para 2024. Se você quiser ver como eles aparecem como JSON de entrada clique aqui para 1000 registros aleatórios, mas aqui está o resultado final como um serviço de feição:
Reclamações de Clientes FCC - chamadas indesejadas
Algumas pesquisas revelam que existem várias abordagens comuns para paginação:
- Parâmetros offset e limit definindo a posição da linha inicial e a contagem de linhas, lendo dados ordenados.
- Esta abordagem pode incluir outro parâmetro para qual propriedade define a ordem de classificação
- Número da página e (opcionalmente) parâmetros de tamanho da página.
- Paginação baseada em consulta, onde uma linha inicial é definida por uma consulta lógica, implicando qualquer próxima consulta.
- Consulta baseada em tempo, um caso especial de paginação baseada em consulta.
- Paginação baseada em cursor, onde a API fornece nomes das páginas, incluindo qualquer próxima página, no resultado.
- Combinações dos acima.
As duas primeiras abordagens são as mais simples (e as únicas que usei), o servidor faz os cálculos da construção da página e o cliente só precisa acompanhar um contador simples, enviando requisições até que os dados se esgotem.
Aqui está um exemplo de uma API baseada em offset e limit e aqui está um exemplo de uma API baseada em página.
Para um exemplo do #6, combinando #3 & #4, você pode ler sobre consulta a camadas de feição hospedadas. O ArcGIS cuida da construção das consultas das camadas para você.
E quanto à análise simplificada também? Temos que transformar registros assim em colunas tipadas e geometria!
{
"issue_type" : "Phone",
"caller_id_number" : "830-210-2001",
"state" : "IL",
"method" : "Wired",
"advertiser_business_phone_number" : "None",
"issue_time" : "8:41 am",
"issue" : "Unwanted Calls",
"zip" : "60629",
"type_of_call_or_messge" : "Live Voice",
"issue_date" : "2024-01-04T00:00:00.000",
"id" : "3739134",
"location_1" : {
"latitude" : "41.781382",
"human_address" : "{\"address\": \"\", \"city\": \"IL\", \"state\": \"\", \"zip\": \"60629-5219\"}",
"needs_recoding" : false,
"longitude" : "-87.732853"
}
}
Sem problema! Vamos começar.
Paginação
Estamos chamando uma REST API aqui, e ela oferece uma resposta paginada. No ArcGIS Data Interoperability isso significa chamar o transformador HTTPCaller em um loop, neste caso com parâmetros offset, limit e order, incrementando o valor do offset a cada chamada, até que todos os dados sejam recebidos e a resposta seja um array vazio. Você talvez não soubesse que é possível fazer loop em um ambiente de programação visual, mas é possível, e é fácil. O transformador customizado verde menta chamado "UnwantedCallsLooper", perto do canto superior esquerdo do meu espaço de trabalho, faz esse trabalho. É um transformador customizado com loop.
Espaço de trabalho ETL principal
O transformador customizado está embutido (incluído) na tela Principal, ele vive em sua própria aba homônima. Você cria transformadores customizados selecionando um ou mais transformadores comuns na tela Principal e então um menu contextual acessível pelo clique direito oferece a opção de criação do transformador customizado. No meu caso selecionei apenas um transformador HTTPCaller.
Após criar o transformador customizado houve mais etapas de edição para configurar o loop:
- Adicionar uma conexão de retorno do loop usando uma escolha do menu contextual na tela
- Adicionar um teste para conclusão antes do retorno do loop
- Incrementar o parâmetro offset
Abaixo está como meu transformador customizado fica. Em tempo de execução cada feição chegando da tela Principal tem um atributo offset usado pelo transformador HTTPCaller. Os parâmetros limit e order não mudam então estão “codificados” no HTTPCaller. O fluxo inferior é a condição loop-until - se a resposta não for um array vazio os dados não estão esgotados, então incremente o offset e faça o loop!
Transformador customizado com loop
Análise
Cada resposta da API é um array de structs JSON e está contida em um atributo chamado "_response_body." O array é explodido em feições separadas com um JSONFragmenter. O parâmetro JSON Query significa apenas que estamos fragmentando o array do nível superior e as outras configurações garantem a entrega dos fragmentos que se parecem com o bloco de código acima.
JSONFragmenter
Agora analisamos cada feição fragmento com um JSONExtractor.
JSONExtractor
A grade Extract Queries define os nomes dos atributos de saída e de onde vêm os dados no fragmento. O Consultas JSON seguem uma sintaxe simples que você pode digitar, mas há um truque simples para obter um seletor que permita navegar na estrutura JSON e automatizar a geração de consultas. Antes do JSONExtractor, temporariamente amostre uma única feição e grave-a em um arquivo, então defina temporariamente sua fonte de entrada do JSONExtractor para este arquivo e você terá um seletor útil para suas consultas! Quando você tiver preenchido suas consultas de extração, remova o Sampler e redefina sua fonte de entrada do JSONFragmenter para ser o documento em _response_body.<\/P>
Então, isso é paginação e análise desmistificadas!<\/STRONG> No download do blog há dois arquivos fmw de workspace fonte. CreateFC cria uma saída de geodatabase de arquivo e é onde eu descobri o processamento dos dados, como corrigir erros de dados que impediam a criação de um campo datetime. Eu queria uma classe de feição inicial de qualquer forma para simbolizar e compartilhar como meu serviço de feição hospedado alvo. UpdateFS aproveita as etapas de processamento de dados em CreateFC mas contém o transformador personalizado de loop e alguma lógica para detectar e aplicar mudanças nos dados sempre que a ferramenta ETL for executada, que é o que você provavelmente precisará em produção.<\/P>
Por favor, comente neste post com quaisquer perguntas e observações. Continue paginando!<\/P>
<\/P>