Het Probleem
Ik probeer hier een nieuw acroniem uit - B2G - Business To GIS - wat betekent de levering van extern beheerde data in ArcGIS. Het is heel gebruikelijk dat externe ("business") systemen een REST API aanbieden die je kunt aanroepen om data in een algemeen formaat zoals JSON te krijgen, maar het is ook heel gebruikelijk dat de server een dataset in meerdere stukken (d.w.z. "pagina's") levert, en dat de JSON niet in een goed gedefinieerde dialect zoals GeoJSON is - je moet het parsen naar kolommen, mogelijk uit struct- of array-objecten.
Deze post gaat over het overwinnen van de twee uitdagingen van paginering en parsen, zonder coderen, met behulp van ArcGIS Data Interoperability.
Mijn onderwerpdata is Federal Communications Commission klachten van klanten over ongewenste oproepen, gefilterd voor 2024. Als je wilt zien hoe het eruitziet als inkomende JSON klik hier voor 1000 willekeurige records, maar hier is het eindresultaat als een feature service:
FCC Customer Complaints - unwanted calls
Wat onderzoek onthult dat er verschillende veelvoorkomende pagineringsbenaderingen zijn:
- Offset- en limietparameters die de startpositie van de rij en het aantal rijen definiëren, waarbij geordende data wordt gelezen.
- Deze benadering kan een andere parameter bevatten voor welke eigenschap de sorteervolgorde bepaalt
- Paginanummer en (optioneel) paginagrootte parameters.
- Query-gebaseerde paginering, waarbij een startrij wordt gedefinieerd door een logische query, wat elke volgende query impliceert.
- Tijdbased query, een speciaal geval van query-gebaseerde paginering.
- Cursor-gebaseerde paginering, waarbij de API paginanamen levert, inclusief elke volgende pagina, in het resultaat.
- Combinaties van bovenstaande.
De eerste twee benaderingen zijn het eenvoudigst (en de enige die ik heb gebruikt), de server doet de pagina-bouw berekeningen en de client hoeft alleen maar een eenvoudige teller bij te houden, verzoeken te sturen totdat de data op is.
Hier is een voorbeeld van een offset- en limietgebaseerde API en hier is een voorbeeld van een pagina-gebaseerde API.
Voor een voorbeeld van #6, combinatie van #3 & #4, kun je lezen over queryen van gehoste feature layers. ArcGIS zorgt voor het bouwen van laagqueries voor jou.
Hoe zit het met parsen ook eenvoudig maken? We moeten records zoals deze omzetten in getypeerde kolommen en geometrie!
{
"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"
}
}
Geen probleem! Laten we beginnen.
Paginering
We roepen hier een REST API aan, en deze biedt een gepagineerd antwoord. In ArcGIS Data Interoperability betekent dit dat je de HTTPCaller-transformer in een lus aanroept, in dit geval met offset, limit en order-parameters, waarbij je bij elke oproep de offsetwaarde verhoogt totdat alle data ontvangen is en het antwoord een lege array is. Je wist misschien niet dat je kunt lussen in een visuele programmeeromgeving, maar dat kan wel, en het is eenvoudig. De muntgroene custom transformer "UnwantedCallsLooper" linksboven in mijn werkruimte doet het werk. Het is een loopende custom transformer.
Ouder ETL werkruimte
De custom transformer is ingebed (opgenomen) in het Main canvas, het leeft in zijn eigen eponiem genoemde tabblad. Je maakt custom transformers door één of meer gewone transformers te selecteren in het Main canvas waarna een contextmenu toegankelijk via rechtsklikken een keuze voor custom transformer creatie biedt. In mijn geval selecteerde ik slechts één HTTPCaller transformer.
Na het maken van de custom transformer waren er meer bewerkingsstappen om lussen op te zetten:
- Voeg een loop return verbinding toe via een contextmenu keuze in het canvas
- Voeg een test voor voltooiing toe vóór de loop return
- Verhoog de offset parameter
Hieronder zie je hoe mijn custom transformer eruitziet. Tijdens runtime heeft elk feature dat binnenkomt vanuit het Main canvas een offset attribuut dat door de HTTPCaller transformer wordt gebruikt. De limit en order parameters veranderen niet dus zijn ze “hard gecodeerd” in de HTTPCaller. De onderste stroom is de loop-tot conditie - als het antwoord niet een lege array is dan is de data niet uitgeput, dus verhoog de offset en lus door!
Loopende custom transformer
Parsen
Elk API antwoord is een array van JSON structs en zit in een attribuut genaamd "_response_body." De array wordt gesplitst in aparte features met een JSONFragmenter. De JSON Query parameter betekent gewoon dat we fragmenteren op het topniveau array en de andere instellingen zorgen ervoor dat fragmenten worden geleverd die eruitzien als het codeblok hierboven.
JSONFragmenter
Nu parsen we elk fragment feature met een JSONExtractor.
JSONExtractor
The Extract Queries grid defines the output attribute names and where the data comes from in the fragment. The JSON-queries volgen een eenvoudige syntaxis die je kunt invoeren, maar er is een eenvoudige truc om een picker te laten navigeren door de JSON-structuur en het genereren van queries te automatiseren. Voor de JSONExtractor, tijdelijk sample een enkele feature en schrijf deze naar een bestand, stel dan tijdelijk je JSONExtractor invoerbron in op dit bestand en je krijgt een handige picker voor je queries! Wanneer je je extractqueries hebt ingevuld, verwijder dan de Sampler en zet je JSONFragmenter invoerbron terug naar het document in _response_body.<\/P>
Zo zijn paginering en parsing ontrafeld!<\/STRONG> In de blogdownload zijn er twee workspace source fmw-bestanden. CreateFC maakt een file geodatabase-uitvoer aan en is waar ik de gegevensverwerking heb uitgezocht, zoals het corrigeren van datafouten die het aanmaken van een datetime-veld tegenhielden. Ik wilde toch al een initiële feature class om te symboliseren en te delen als mijn doel-hosted feature service. UpdateFS leent de gegevensverwerkingsstappen uit CreateFC maar bevat de looping custom transformer en wat logica om dataveranderingen te detecteren en toe te passen telkens wanneer de ETL-tool wordt uitgevoerd, wat waarschijnlijk nodig is in productie.<\/P>
Gelieve in dit bericht te reageren met vragen en observaties. Blader gerust verder!<\/P>
<\/P>