简体   繁体   中英

What kind of database schema would I use to store users' transaction histories?

I have a series of python objects, each associated with a different user, eg, obj1.userID = 1 , obj2.userID = 2 , etc. Each object also has a transaction history expressed as a python dict, ie, obj2.transaction_record = {"itemID": 1, "amount": 1, "date": "2011-01-04"} etc.

I need these objects to persist, and transaction records may grow over time. Therefore, I'm thinking of using an ORM like sqlalchemy to make this happen.

What kind of database schema would I need to specify to store these objects in a database?

I have two alternatives, but neither seems like the correct thing to do:

  1. Have a different table for each user:

CREATE TABLE user_id ( itemID INT PRIMARY KEY, amount INT, date CHARACTER(10) );

  1. Store the transaction history dict as a BLOB of json:

CREATE TABLE foo ( userID INT PRIMARY KEY, trasaction_history BLOB);

Is there a cleaner way to implement this?

Instead of thinking of your transaction history as a large, mutable thing, think of it as a collection of immutable records. Store each record as a row in a dedicated transaction table, eg

CREATE TABLE users (
    id INTEGER PRIMARY KEY
);

CREATE TABLE transactions (
    id INTEGER PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    amount INTEGER,
    stamp TIMESTAMP
);

-- Repeat as necessary
INSERT INTO transactions (user_id, amount, stamp)
VALUES (1, 3, '2016-01-24 00:00:00');

Now you can insert individual records and see a user's whole transaction history with something like

SELECT id, amount, stamp
FROM transactions
WHERE user_id = <SOME_USER_ID>
ORDER BY stamp ASC;

Your example seems entirely suited for a relational database. You have a one-to-one relationship between users and transactions, and the SQLAlchemy ORM can express this nicely.

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    transaction_id = Column(Integer, ForeignKey('transaction.id'))
    transaction = relationship(
        "Transaction", uselist=False, backref=backref("user", uselist=False))


class Transaction(Base):
    __tablename__ = 'transaction'
    id = Column(Integer, primary_key=True)
    amount = Column(Integer)
    date = Column(DateTime, default=datetime.datetime.now)

interface:

>>> t = Transaction(amount=100)
>>> u = User()
>>> u.transaction = t
>>> session.add(u)
>>> session.commit()
>>> u = session.query(User).first()
>>> u.transaction.amount
100
>>> u.transaction.date
datetime.datetime(2016, 1, 24, 16, 21, 38, 683959)

I don't know why you want to have the transaction expressed as an arbitrary Python object, but if it has variable columns you can just encode the transaction object as JSON. SQLAlchemy has ways of fully expressing and automating this :

class JSONEncodedDict(TypeDecorator):
    "Represents an immutable structure as a json-encoded string."

    impl = VARCHAR

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)
        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value

如果您直到现在还没有决定要使用哪种数据库,我建议您选择mongodb作为数据库服务器和mongoengine模块来保留数据,这就是您所需要的,mongoengine有一个DictField可存储在其中直接使用python字典,非常容易学习。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM