Meta-Jdbc Driver

Einleitung

Der MetaJdbc Treiber ermöglicht das Lesen von Meta-Daten (Facebook Graph API, Instagram Business und Meta Ads) über JDBC mit SQL.

Es gelten folgende Konventionen:

  • als Datenbank wird die Verbindung jdbc:meta: verwendet
  • die JDBC-URL enthält die Graph-API-Basis-URL (jdbc:meta:https://graph.facebook.com/v25.0)
  • Endpunkte, Felder und Metriken werden in einer Spec-Datei (JSON, YAML oder INI) konfiguriert
  • als Schema wird public verwendet (Standard)
  • SQL-Tabellennamen sind vordefiniert und an feste Fetch-Strategien gebunden (z. B. fbk_page_insights_daily, meta_ad_account)
  • Metriken und API-Parameter kommen aus der Spec und sind zur Laufzeit anpassbar
  • der Treiber unterstützt nur SELECT (read-only)
  • ein System-User-Token (Super-Admin) reicht — Page-Tokens und Ad-Accounts werden intern aufgelöst

Features

  • Facebook Pages und verknüpfte Instagram-Accounts über /me/accounts
  • Facebook Page Insights (täglich)
  • Instagram Page Insights (Snapshot und täglich)
  • Instagram Media Listing und Media Insights
  • Meta Ad Accounts, Campaigns, Ad Sets, Ads
  • Async Ad Insights (meta_ad_stats, meta_conversion_stats)
  • Spec-Datei zur Laufzeit anpassbar (Metriken, Limits, Endpunkte, Filter)
  • 12 vordefinierte Tabellen mit spezialisierter API-Logik
  • Systemtabellen für Tabellen, Spalten und Primärschlüssel

JDBC URL

jdbc:meta:https://graph.facebook.com/v25.0

Der Teil nach jdbc:meta: ist die Graph-API-Basis-URL inklusive API-Version. Sie hat Vorrang vor api.baseUrl in der Spec.

Beispiel-Verbindung (Java)

Properties props = new Properties();
props.setProperty("token", "EAAx...");
props.setProperty("spec", "/opt/datasqill/config/meta-spec.json");

Connection conn = DriverManager.getConnection(
    "jdbc:meta:https://graph.facebook.com/v25.0", props);

Zeitraum und Objektauswahl gehören ins SQL (FILTER), nicht in die Connection — siehe FILTER.

Connection Properties

Property Beschreibung Erforderlich
token System-User-Access-Token (Facebook Login for Business) Ja
spec Pfad zur Spec-Datei (.json, .yaml, .yml, .ini; Dateisystem oder classpath:...) Nein (Default: eingebaute Spec)
von_dt Beginn des Zeitraums (yyyy-MM-dd) Per FILTER im SQL (Fallback: Connection Property)
bis_dt Ende des Zeitraums (yyyy-MM-dd) Per FILTER im SQL (Fallback: Connection Property)
load_type delta (Standard) oder full für async Ad Insights Per FILTER oder Connection Property
stdoutlog Debug-Ausgabe: meta, http, rows, cursor oder all (kombinierbar mit +) Nein

Property-Namen sind case-insensitive. config ist ein Alias für spec.

Spec-Pfad:

/opt/datasqill/config/meta-spec.json
/opt/datasqill/config/meta-spec.yaml
classpath:de/softquadrat/jdbc/meta/meta-spec.json

datasqill keyfile

Im keyfile werden nur statische Verbindungsdaten gesetzt (token, spec). Der Ladezeitraum steht im SQL:

jdbc:meta:https://graph.facebook.com/v25.0:dboptionlist={token=EAAx...,spec=/opt/datasqill/meta-spec.json}:

Authentifizierung

Es wird ein System-User-Token verwendet. Der Treiber:

  1. ruft GET /me/accounts auf und erhält Page-Access-Tokens
  2. nutzt diese Page-Tokens für Facebook- und Instagram-Insights
  3. nutzt den User-Token für alle act_* Ad-Account-Aufrufe

Erforderliche Berechtigungen (Auszug):

  • pages_read_engagement, pages_show_list
  • instagram_basic, instagram_manage_insights
  • ads_read (für Paid Media)

Nutzungsmuster

Pro ETL-Job eine JDBC-Verbindung öffnen und ein SELECT pro Zieltabelle ausführen.

SELECT page_id, name, insta_user_id FROM fbk_page_insights;

SELECT page_id, dat, page_total_media_view_unique
FROM fbk_page_insights_daily
FILTER von_dt='2025-01-01' AND bis_dt='2025-01-31'
;

SELECT ad_account_id, name FROM meta_ad_account;

SELECT ad_account_id, ad_id, impressions, datum
FROM meta_ad_stats
FILTER von_dt='2025-01-01' AND bis_dt='2025-01-31' AND load_type=delta
;

Der Treiber iteriert intern über alle Pages bzw. Ad-Accounts. Mit FILTER können Zeitraum und einzelne Pages eingegrenzt werden. Es gibt kein WHERE und kein LIMIT.

Hinweis: datasqill-SQL unterstützt keine Zeilenkommentare mit --. In meta-staging.sql stehen nur ausführbare Statements.

Caching innerhalb einer Verbindung

Daten Verhalten
Page-Liste (/me/accounts) einmal pro Verbindung, dann Cache
Ad-Account-Liste einmal pro Verbindung, dann Cache
Insights-Daten bei jedem SELECT neu von der API

Mehrere SELECTs in derselben Verbindung sparen den erneuten /me/accounts-Aufruf. Derselbe SELECT zweimal führt den kompletten API-Lauf erneut aus.

Tabellen

Social Media (Facebook / Instagram)

Tabelle Inhalt von_dt/bis_dt
fbk_page_insights Facebook Pages + verknüpfte IG-Accounts Nein
fbk_page_insights_daily Facebook Page Insights pro Tag Ja
ins_page_insights Instagram Follower-Snapshot Nein
ins_page_insights_daily Instagram Account Insights pro Tag Ja
ins_media Instagram Media-Objekte (Posts/Reels) Optional (Filter nach Publish-Datum)
ins_media_insights Instagram Media Insights (Lifetime) Ja (Filter nach Publish-Datum)

Paid Media (Meta Ads)

Tabelle Inhalt von_dt/bis_dt
meta_ad_account Ad Accounts Nein
meta_campaign Campaigns (alle Accounts) Nein
meta_adset Ad Sets Nein
meta_ad Ads Nein
meta_ad_stats Ad Performance (async) Ja (bei load_type=delta)
meta_conversion_stats Conversion Stats (async) Ja (bei load_type=delta)

Vollständiges SQL-Beispiel: meta-staging.sql

Spec-Datei

Die Spec definiert API-Endpunkte, abgefragte Felder/Metriken, Limits und Filter. Format: JSON (empfohlen), YAML oder INI (Legacy).

Vollständige Referenz-Spec: meta-spec.json
Kurzbeispiel YAML: meta-spec-example.yaml

Struktur (JSON)

{
  "api": {
    "version": "v25.0",
    "baseUrl": "https://graph.facebook.com"
  },
  "fbk_page_insights_daily": {
    "endpoint": "insights",
    "fields": [
      "page_total_media_view_unique",
      "page_media_view",
      "page_post_engagements"
    ],
    "tablename": "stage.fbk_page_insights_daily"
  }
}

Struktur (YAML)

api:
  version: v25.0
  baseUrl: https://graph.facebook.com

fbk_page_insights_daily:
  endpoint: insights
  fields:
    - page_total_media_view_unique
    - page_post_engagements

Spec-Abschnitte

Jeder Schlüssel auf Root-Ebene (außer api) ist der Name einer vordefinierten SQL-Tabelle und parametrisiert deren API-Aufrufe (fields, endpoint, limit, …). Neue Tabellennamen lassen sich nicht per Spec hinzufügen.

Feld Beschreibung
endpoint Graph-API-Endpunkt relativ zur Page/Ad Account ID
endpoints Kommagetrennte Endpunkte (nur ad_account, z. B. owned + client accounts)
fields Abzufragende Felder oder Insights-Metriken (Array oder CSV-String)
limit Page-Size für paginierte Requests
filtering Meta-API-Filtering-Ausdruck (Paid Media)
breakdowns Breakdowns für async Insights
tablename Staging-Zielname (Dokumentation) JDBC ignoriert

Dynamische Metrik-Spalten

Bei fbk_page_insights_daily, ins_page_insights_daily und ins_media_insights werden die Metrik-Spalten aus fields in der Spec gelesen. Neue Metriken können in der Spec ergänzt werden, ohne den Treiber neu zu kompilieren.

Stammdaten-Spalten (page_id, media_id, ad_account_id, …) bleiben im Treiber fest definiert.

Was die Spec steuert — und was nicht

Die Graph API hat pro Datentyp unterschiedliche Lademuster (Page-Iteration, Async-Jobs, Media-Pagination, Pivot-Logik), die im Treiber als feste Fetch-Strategien implementiert sind.

Konfiguration Spec Treiber (Java)
SQL-Tabellenname Nein Ja — 12 feste Namen
Fetch-Strategie (wie geladen wird) Nein Ja — z. B. Page Insights Daily, Async Ad Stats
Stammdaten-Spalten (page_id, ad_account_id, …) Nein Ja
Metrik-Spalten (fields) Ja Basis-Spalten + Spec
API-Endpunkte, Limits, Filter, Breakdowns Ja
tablename (Staging-Ziel) Ja JDBC ignoriert

Praktische Folgen:

  • Metriken anpassen, deprecated Metrics entfernen → Spec editieren, fertig
  • Neue Tabelle mit bekanntem Lademuster → zukünftige Treiber-Erweiterungen

Jeder Spec-Abschnitt (z. B. fbk_page_insights_daily) ist an genau eine vordefinierte SQL-Tabelle gekoppelt. Der Abschnittsname muss dem Tabellennamen entsprechen.

SQL-Syntax

Grundlegende SELECT-Abfrage

SELECT page_id, name, insta_user_id
FROM fbk_page_insights
;
SELECT page_id, dat, page_total_media_view_unique, page_post_engagements
FROM fbk_page_insights_daily
FILTER von_dt='2025-01-01' AND bis_dt='2025-01-31'
;
SELECT page_id, dat, page_total_media_view_unique
FROM fbk_page_insights_daily
FILTER von_dt='2025-01-01' AND bis_dt='2025-01-31' AND page_id='330419580652874'
;

FILTER (Zeitraum und Objektauswahl)

In datasqill-SQL heißt die Klausel FILTER (nicht WHERE). Sie steuert API-Parameter des Treibers — vor allem den Ladezeitraum und optional einzelne Pages.

Syntax: param=value, mehrere Parameter mit AND verknüpft. Werte in einfachen Anführungszeichen oder unquoted.

FILTER-Parameter Alias Wirkung
von_dt from_date Beginn des Zeitraums (yyyy-MM-dd)
bis_dt to_date Ende des Zeitraums (yyyy-MM-dd)
page_id Nur diese Facebook-Page laden
insta_user_id Nur diesen Instagram-Account laden
load_type delta oder full für async Ad Insights

Priorität: FILTER-Werte überschreiben Connection Properties. In datasqill-ETL-Jobs den Zeitraum immer im SQL setzen — Connection/keyfile pflegt nur der Administrator (token, spec).

Beispiele:

SELECT ad_id, impressions, date_start
FROM meta_ad_stats
FILTER von_dt='2025-01-01' AND bis_dt='2025-01-31' AND load_type=delta
;

SELECT insta_user_id, dat, reach
FROM ins_page_insights_daily
FILTER from_date='2025-01-01' AND to_date='2025-01-31' AND insta_user_id='17841400000'
;

Nicht unterstützt

  • INSERT, UPDATE, DELETE
  • WHERE, ORDER BY
  • SQL-Zeilenkommentare (-- …)
  • COLUMNS-Klausel

Spaltenauswahl per SELECT funktioniert — es werden nur die referenzierten Spalten zurückgegeben.

Reservierte Spaltennamen

Spaltennamen, die SQL-Schlüsselwörter sind, müssen in doppelten Anführungszeichen stehen:

SELECT insta_user_id, media_id, "timestamp", permalink FROM ins_media;

Betrifft u. a. timestamp in ins_media und ins_media_insights.

Instagram follower_count (Daily)

Die Metrik follower_count in ins_page_insights_daily kann bei der Graph API nur für die letzten 30 Tage (ohne heute) abgefragt werden. Für ältere Tage im FILTER-Zeitraum liefert der Treiber die übrigen Metriken (reach, likes, …) und setzt follower_count auf NULL — ohne API-Fehler.

System-Tabellen

Über das Schema system stehen virtuelle Tabellen zur Verfügung:

Tabelle Inhalt
table_list Alle registrierten Meta-Tabellen
column_list Spalten (inkl. dynamischer Metriken aus der Spec)
pk_list Primärschlüssel
SELECT table_name, remarks
FROM system.table_list
WHERE table_name LIKE 'meta_%'
;

SELECT column_name, type_name
FROM system.column_list
WHERE table_name = 'fbk_page_insights_daily'
;

Interner Ablauf

Social Media

token → GET /me/accounts → alle Pages
  ├─ fbk_page_insights        → Page-Stammdaten
  ├─ fbk_page_insights_daily  → GET /{page-id}/insights (pro Page)
  ├─ ins_page_insights        → GET /{ig-user-id}
  ├─ ins_page_insights_daily  → GET /{ig-user-id}/insights (pro Tag)
  ├─ ins_media                → GET /{ig-user-id}/media
  └─ ins_media_insights       → GET /{media-id}/insights (pro Media)

Paid Media

token → Ad Accounts (owned + client)
  ├─ meta_ad_account          → Stammdaten
  ├─ meta_campaign/adset/ad   → paginierte Entity-Calls pro Account
  └─ meta_ad_stats            → POST async insights → poll → GET results

Fehlersuche

stdoutlog=meta+http+rows
Level Ausgabe
meta API-Aufrufe, Page-/Account-Auflösung, übersprungene Metriken
http HTTP-Methode und URL
rows Gelesene Zeilen pro Batch
cursor Geöffnete Tabelle

Typische Fehler:

Meldung Ursache / Lösung
(#100) The value must be a valid insights metric Metrik in Graph API v25 deprecated — aus Spec entfernen oder Treiber überspringt sie einzeln
Missing connection property "von_dt" FILTER von_dt='…' AND bis_dt='…' ergänzen (Pflicht bei Daily-/Delta-Tabellen)
Sorry, I cannot understand -- … Keine ---Kommentare in datasqill-SQL — Kommentarzeile entfernen
mismatched input 'timestamp' Spalte "timestamp" in doppelten Anführungszeichen quoten
follower_count … last 30 days Historische Tage: Treiber überspringt follower_count automatisch; neuen Build nutzen
HTTP 429 Rate Limit — Treiber retried automatisch; Last reduzieren
Lange Laufzeit ohne Ausgabe Normal bei vielen Pages/Media — stdoutlog aktivieren

Hinweise

API-Version und Metriken

Meta depreciert regelmäßig Insights-Metriken (z. B. page_impressions_unique in v25). Die Default-Spec nutzt aktuelle Metriken (page_total_media_view_unique, page_media_view). Bei API-Fehlern die Meta Insights-Dokumentation prüfen.

Instagram Media Insights

ins_media_insights führt einen API-Call pro Media-Objekt aus. Bei vielen Posts kann ein Load deutlich dauern.

Ungültige Metriken pro media_type (FEED, REELS, STORY) werden automatisch übersprungen.

Beispiele