2012-11-05 9 views
5

Sto provando a usare il framework olap di Python cubes su un database molto semplice, ma sto riscontrando qualche difficoltà nel partecipare alle tabelle.Cubo di Python OLAP Framework: come lavorare con i join?

mio schema è simile al seguente:

Users table 
ID | name 

Products table 
ID | name | price 

Purchases table 
ID | user_id | product_id | date 

E il modello cubetti:

{ 
    'dimensions': [ 
     {'name': 'user_id'}, 
     {'name': 'product_id'}, 
     {'name': 'date'}, 
    ], 
    'cubes': [ 
     { 
      'name': 'purchases', 
      'dimensions': ['user_id', 'product_id', 'date'], 
      'measures': ['price'] 
      'mappings': { 
       'purchases.user_id': 'users.id', 
       'purchases.product_id': 'products.id', 
       'purchases.price': 'products.price' 
      }, 
      'joins': [ 
       { 
        'master': 'purchases.user_id', 
        'detail': 'users.id' 
       }, 
       { 
        'master': 'purchases.product_id', 
        'detail': 'products.id' 
       } 
      ] 
     } 
    ] 
} 

Ora vorrei per visualizzare tutti gli acquisti, che mostra il nome del prodotto, il nome e la data di acquisto dell'utente. Non riesco a trovare un modo per farlo. La documentazione è un po 'scarsa.

Grazie

+0

OLAP non è progettato per eseguire join. Utilizzare invece un database SQL, forse. –

+2

@AaronWatters Il framework Python's Cubes fornisce questa funzionalità. È un backend MySQL. – user1491915

+0

Per chiarire: i join sono nascosti all'utente finale, fanno parte della mappatura logico-fisico e sono specificati nel modello logico. Inoltre, Cubes ha molti backend di database relazionali, non solo MySQL, tutti backend supportati da SQLAlchemy. Ciò include: PostgreSQL, Oracle, SQLite e molti altri. – Stiivi

risposta

14

Prima di tutto fissare il modello un po '. Nel tuo schema hai più attributi per dimensione: id e nome, potresti avere più dettagli in futuro. È possibile aggiungerli specificando gli attributi come elenco: "attriubtes": ["id", "name"]. Si noti inoltre che la dimensione è denominata come entità product non come chiave id_product. La chiave id_product è solo un attributo della dimensione product, così come lo è name o in futuro forse category. La dimensione riflette il punto di vista degli analisti.

Per il momento, ignoriamo il fatto che la data dovrebbe essere una dimensione speciale e considerare la data come chiave a valore singolo, ad esempio un anno, per non complicare le cose qui.

"dimensions": [ 
    {"name": "user", "attributes": ["id", "name"]}, 
    {"name": "product", "attributes": ["id", "name"]}, 
    {"name": "date"} 
], 

Perché abbiamo cambiato i nomi delle dimensioni, dobbiamo cambiare loro in lista dimensione del cubo:

"cubes": [ 
    { 
     "name": "purchases", 
     "dimensions": ["user", "product", "date"], 
     ... 

schema riflette classico schema transazionale, non tradizionale schema di data warehouse. In questo caso, devi essere esplicito, come sei, e menzionare tutte le mappature necessarie. La regola è: se l'attributo appartiene a una tabella dei fatti (vista logica), la chiave è solo attribute, ad esempio price, nessuna specifica tabella. Se l'attributo appartiene a una dimensione, ad esempio product.id, la sintassi è dimension.attribute. Il valore del dizionario dei mapping è la tabella fisica e la colonna fisica. Vedi more information about mappings. Mappature per lo schema simile:

"mappings": { 
    "price": "products.price", 
    "product.id": "products.id", 
    "product.name": "products.name", 
    "user.id": "users.id", 
    "user.name": "users.name" 
} 

che non avrebbe dovuto scrivere mappature se lo schema era:

fact purchases 
id | date | user_id | product_id | amount 

dimension product 
id | name | price 

dimension user 
id | name 

In questo caso sarà necessario unisce solo, perché tutti gli attributi di dimensione sono nel loro rispettivo tabelle dimensionali. Nota il amount nella tabella dei fatti, che nel tuo caso, poiché non hai count di prodotti acquistati per acquisto, sarebbe lo stesso di price in product.

Ecco il modello aggiornato per il modello:

{ 
    "dimensions": [ 
     {"name": "user", "attributes": ["id", "name"]}, 
     {"name": "product", "attributes": ["id", "name"]}, 
     {"name": "date"} 
    ], 
    "cubes": [ 
     { 
      "name": "purchases", 
      "dimensions": ["user", "product", "date"], 
      "measures": ["price"], 
      "mappings": { 
       "price": "products.price", 
       "product.id": "products.id", 
       "product.name": "products.name", 
       "user.id": "users.id", 
       "user.name": "users.name" 
      }, 
      "joins": [ 
       { 
        "master": "purchases.user_id", 
        "detail": "users.id" 
       }, 
       { 
        "master": "purchases.product_id", 
        "detail": "products.id" 
       } 
      ] 
     } 

    ] 
} 

È possibile provare il modello senza scrivere codice Python, semplicemente utilizzando il comando slicer.Per questo è necessario slicer.iniconfiguration file:

[server] 
backend: sql 
port: 5000 
log_level: info 
prettyprint: yes 

[workspace] 
url: sqlite:///data.sqlite 

[model] 
path: model.json 

Variazione url in [workspace] per puntare al database e cambiare path in [model] per puntare al file di modello. Ora si può provare:

curl "http://localhost:5000/aggregate" 

cercano anche di drill-down:

curl "http://localhost:5000/aggregate?drilldown=product" 

Se avete bisogno di ulteriore aiuto, fammelo sapere, io sono l'autore Cubes.

+0

Grazie, ottima soluzione! – user1491915

+0

"Al momento ignoriamo il fatto che la data dovrebbe essere una dimensione speciale" Se uno vorrebbe saperne di più, e uno sta usando un archivio dati SQL: il trucco per analizzare una data fino ai suoi campi è spiegato a https://pythonhosted.org/cubes/backends/sql.html#date-data-type – DomQ

+0

I nomi dei campi "id" e "name" hanno significati speciali? –