Существует также df2 <- count(x, c('Year','Month'))
(пакет plyr)
У меня есть пример того, как это сделать в моем блоге на странице http://techspot.zzzeek.org/2012/01/11/django-style-database-routers-in-sqlalchemy/ . В основном вы можете улучшить сеанс, чтобы он выбирал из основного или подчиненного на основе запроса по запросу. Один из возможных сбоев в этом подходе состоит в том, что если у вас есть одна транзакция, которая вызывает шесть запросов, вы можете использовать оба подчиненных в одном запросе ... но там мы просто пытаемся имитировать функцию Django:)
Немного менее волшебный подход, который также устанавливает область использования более явным образом, я использовал декоратор на вызовах вида (что бы они ни называли в Flask), например:
@with_slave
def my_view(...):
# ...
with_slave будет делать что-то вроде этого, предполагая, что у вас есть сеанс и установлены некоторые механизмы:
master = create_engine("some DB")
slave = create_engine("some other DB")
Session = scoped_session(sessionmaker(bind=master))
def with_slave(fn):
def go(*arg, **kw):
s = Session(bind=slave)
return fn(*arg, **kw)
return go
Идея состоит в том, что вызов Session(bind=slave)
вызывает реестр для получения фактического объекта Session для текущего потока, создавая его, если он не существует, но поскольку мы передаем аргумент, scoped_session будет утверждать, что сеанс, который мы здесь делаем, определенно совершенно новый.
Вы указываете его на «подчиненный» для все последующие SQL. Затем, когда запрос завершен, вы убедитесь, что ваше приложение Flask вызывает Session.remove()
, чтобы удалить реестр для этого потока. Когда реестр будет использоваться в одном и том же потоке, это будет новый сеанс, связанный с «мастером».
Или вариант, который вы хотите использовать «ведомый» только для этого вызова, этот является «более безопасным» в том смысле, что он восстанавливает любое существующее привязку к сеансу:
def with_slave(fn):
def go(*arg, **kw):
s = Session()
oldbind = s.bind
s.bind = slave
try:
return fn(*arg, **kw)
finally:
s.bind = oldbind
return go
. Для каждого из этих декораторов вы можете отменить все, связать сессию с «ведомым», где ставит декоратор он на «хозяине» для операций записи. Если вам нужен случайный ведомый в этом случае, если в Flask было какое-то событие «начать заявку», вы можете настроить его в этой точке.
Или мы можем попробовать другой путь. Например, мы можем объявить два разных класса со всеми атрибутами экземпляра одинаковыми, но атрибут класса __bind__
отличается. Таким образом, мы можем использовать класс rw для чтения / записи и r-класса для чтения только. :)
Я думаю, что этот способ проще и надежнее. :)
Мы объявляем две модели db, потому что мы можем иметь таблицы в двух разных db с одинаковыми именами. Таким образом, мы также можем обойти ошибку «extend_existing», когда две модели с одинаковым __tablename __.
Вот пример:
app = Flask(__name__)
app.config['SQLALCHEMY_BINDS'] = {'rw': 'rw', 'r': 'r'}
db = SQLAlchemy(app)
db.Model_RW = db.make_declarative_base()
class A(db.Model):
__tablename__ = 'common'
__bind_key__ = 'r'
class A(db.Model_RW):
__tablename__ = 'common'
__bind_key__ = 'rw'