SQL & NoSQL — JSONL, MongoDB, Redes Sociais
O SchemaDetector detecta automaticamente o tipo de dado e aplica a estratégia
de encoding correta. O .permafrost resultante é idêntico ao de dados tabulares.
Dados tabulares (CSV, DataFrame)
import permafrost as pf
# CSV
det = pf.SchemaDetector()
df, dtype, manifest = det.detect("vendas.csv")
# dtype = DataType.TABULAR
# DataFrame direto
df, dtype, manifest = det.detect(meu_dataframe)
JSONL (JSON Lines)
Formato usado por dumps do MongoDB, Elasticsearch, APIs REST, redes sociais:
import permafrost as pf
det = pf.SchemaDetector()
df, dtype, manifest = det.detect("posts.jsonl")
# dtype = DataType.SEMI_STRUCTURED
print(f"Detectado: {dtype}")
print(f"Colunas: {list(df.columns)}")
print(f"Linhas: {len(df):,}")
Como o flatten funciona
Dado um documento como:
{
"id": "1001",
"user_id": 42,
"text": "Novo projeto open source!",
"hashtags": ["#python", "#data"],
"mentions": ["@alice"],
"likes": 150,
"created_at": "2024-01-15T10:30:00Z",
"location": {"lat": -23.5, "lon": -46.6, "city": "São Paulo"}
}
O SchemaDetector gera:
| Campo | Tipo | Estratégia | Preditor |
|---|---|---|---|
id |
str | column_scalar | raw_text |
user_id |
int | column_scalar | delta_zigzag |
text |
str | column_scalar | raw_text |
likes |
int | column_scalar | delta_zigzag |
created_at |
datetime | column_scalar | ts_delta_s |
hashtags |
array | json_str | raw_text |
mentions |
array | json_str | raw_text |
location |
nested | json_str | raw_text |
Campos escalares → colunas com preditores colunares completos (máximo ratio).
Arrays e nested → JSON serializado por coluna (LZMA2 ainda encontra padrões).
Freeze de JSONL
import permafrost as pf
det = pf.SchemaDetector()
df, dtype, manifest = det.detect("posts.jsonl")
metrics = pf.freeze(df, "posts.permafrost", codec=pf.CODEC_LZMA2)
print(f"Ratio: {metrics['ratio']:.2f}×")
# 5.000 posts Twitter → ratio 33×
MongoDB dump
import permafrost as pf
import json
# Dump do mongodump --out=dump.jsonl
det = pf.SchemaDetector()
df, dtype, manifest = det.detect("colecao.jsonl")
metrics = pf.freeze(df, "colecao.permafrost", partition_by="created_year")
# Ou via pymongo diretamente
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
col = client["meu_banco"]["pedidos"]
docs = list(col.find({}, {"_id": 0}))
df, dtype, manifest = det.flatten(docs)
metrics = pf.freeze(df, "pedidos.permafrost")
Dados de redes sociais
import permafrost as pf, json
det = pf.SchemaDetector()
# Twitter/X export
df, _, _ = det.detect("tweets.jsonl")
pf.freeze(df, "tweets.permafrost")
# Instagram export (JSON)
with open("instagram_export.json") as f:
posts = json.load(f)["media"]
df, _, _ = det.flatten(posts)
pf.freeze(df, "instagram.permafrost")
Recuperar dados originais (thaw → reconstruct)
Após o thaw, os campos array e nested estão como JSON strings. Para reconstruir os documentos originais:
import permafrost as pf
import json
df = pf.unfreeze("posts.permafrost")
# Reconstruir documentos
def reconstruct(row):
doc = row.to_dict()
# Desserializar campos que foram JSON-encoded
for col in ["hashtags", "mentions", "location"]:
if col in doc and isinstance(doc[col], str):
doc[col] = json.loads(doc[col])
return doc
documentos = [reconstruct(df.iloc[i]) for i in range(len(df))]
Benchmark — JSONL Social Media
| Dado | Original | .permafrost | Ratio |
|---|---|---|---|
| 5.000 posts (hashtags, mentions, nested location) | 1.44 MB | 0.043 MB | 33× |
| JSONL + LZMA2 direto (sem Permafrost) | 1.44 MB | 0.046 MB | 31× |
| Vantagem Permafrost | — | +7% menor | + thaw seletivo |
Por que o Permafrost vence
A diferença de ratio não é dramática para JSON puro. O ganho real é o thaw seletivo: com o Permafrost você lê só os posts de uma data específica sem descomprimir tudo. Com JSONL+LZMA2 você é obrigado a descomprimir e varrer tudo.