2012-11-05 17 views
5

Ich versuche, Pythons Olap-Framework cubes auf einer sehr einfachen Datenbank zu verwenden, aber ich habe einige Schwierigkeiten beim Verbinden von Tabellen.Python Cubes OLAP Framework - Wie arbeite ich mit Joins?

Mein Schema sieht wie folgt aus:

Users table 
ID | name 

Products table 
ID | name | price 

Purchases table 
ID | user_id | product_id | date 

Und die Würfel Modell:

{ 
    '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' 
       } 
      ] 
     } 
    ] 
} 

Nun würde Ich mag alle Einkäufe anzuzeigen, den Namen des Produkts zeigt, Benutzernamen und das Kaufdatum. Ich kann keinen Weg finden, dies zu tun. Die Dokumentation ist ein bisschen knapp.

Danke

+0

OLAP ist nicht für Joins gedacht. Verwenden Sie stattdessen eine SQL-Datenbank. –

+2

@AaronWatters Python's Cubes Framework bietet diese Funktionalität. Es ist ein MySQL-Backend. – user1491915

+0

Um zu verdeutlichen: Joins sind vom Endbenutzer ausgeblendet, sie sind Teil des Logical-to-Physical-Mappings und im logischen Modell spezifiziert. Auch Cubes hat viele relationale Datenbank-Backends, nicht nur MySQL - alle Backends, die von SQLAlchemy unterstützt werden. Dazu gehören: PostgreSQL, Oracle, SQLite und viele mehr. – Stiivi

Antwort

14

Zuerst ist das Modell ein wenig lassen beheben. In Ihrem Schema haben Sie mehr Attribute pro Dimension: ID und Name, Sie könnten in Zukunft mehr Details haben. Sie können sie hinzufügen, indem Sie Attribute als Liste angeben: "attriubtes": ["id", "name"]. Beachten Sie auch, dass die Dimension als Entität product nicht als Schlüssel id_product benannt ist. Der Schlüssel id_product ist nur ein Attribut der product Dimension, ebenso wie name oder in Zukunft möglicherweise category. Die Dimension spiegelt die Sichtweise der Analysten wider.

Momentan ignorieren wir die Tatsache, dass das Datum eine spezielle Dimension sein sollte und betrachten das Datum als einwertigen Schlüssel, zum Beispiel ein Jahr, um die Dinge hier nicht kompliziert zu machen.

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

Weil wir Namen der Dimensionen verändert, müssen wir sie in der Dimensionsliste Würfel ändern:

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

Ihr Schema spiegelt klassisches Transaktions Schema, nicht traditionelles Data-Warehouse-Schema. In diesem Fall müssen Sie, wie Sie waren, explizit sein und alle notwendigen Zuordnungen erwähnen. Die Regel lautet: Wenn das Attribut zu einer Faktentabelle gehört (logische Sicht), dann ist der Schlüssel nur attribute, z. B. price, keine Tabellenspezifikation. Wenn das Attribut zu einer Dimension gehört, z. B. product.id, lautet die Syntax dimension.attribute. Der Wert des Zuordnungswörterbuchs ist physische Tabelle und physische Spalte. Siehe more information about mappings. Mappings für Ihr Schema wie folgt aussehen:

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

Sie würden nicht Mappings schreiben müssen, wenn Ihr Schema war:

fact purchases 
id | date | user_id | product_id | amount 

dimension product 
id | name | price 

dimension user 
id | name 

In diesem Fall müssen Sie nur beitritt, weil alle Dimensionsattribute in ihren jeweiligen sind Dimensionstabellen. Beachten Sie die amount in der Faktentabelle, die in Ihrem Fall, wie Sie nicht count der gekauften Produkte pro Kauf haben, wäre das gleiche wie price in product. Hier

ist das aktualisierte Modell für Ihr Modell:

{ 
    "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" 
       } 
      ] 
     } 

    ] 
} 

Sie können das Modell versuchen, ohne jeden Python-Code zu schreiben, nur unter Verwendung des slicer Befehls.Dafür werden Sie slicer.ini brauchen configuration file:

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

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

[model] 
path: model.json 

ändern url in [workspace] auf Ihre Datenbank zu zeigen und path in [model] ändern, um Ihre Modelldatei zu zeigen. Jetzt können Sie versuchen:

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

versuchen auch zu Drilldown:

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

Wenn Sie weitere Hilfe benötigen, lass es mich wissen, ich bin der Würfel Autor.

+0

Danke, große Walkthrough! – user1491915

+0

"Vorläufig ignorieren wir die Tatsache, dass Datum eine spezielle Dimension sein sollte" Wenn man mehr darüber wissen möchte, und man einen SQL-Datenspeicher verwendet: Der Trick für das Parsing eines Datums in seine Felder ist erklärt unter https://pythonhosted.org/cubes/backends/sql.html#date-data-type – DomQ

+0

Haben die Feldnamen "id" und "name" eine spezielle Bedeutung? –