Построение запросов с перекрестным соединением баз данных с использованием SQLalchemy ORM и SQLite

У меня есть две базы данных SQLite, содержащие таблицы, которые мне нужно объединить с помощью SQLalchemy. По причинам, я не могу объединить все таблицы в одну базу данных SQLite. Я использую SQLalchemy ORM. Мне не удалось найти в Интернете какое-либо решение, отвечающее моему конкретному случаю.

Мой вопрос в принципе такой же, как SQLAlchemy error query join по базе данных, но проблема исходного плаката была решена с использованием другого решения, которое не соответствует моему варианту использования.

Мой вопрос к мудрым людям из Stackoverflow:

Я хочу сымитировать следующий SQL-запрос:

SELECT DISTINCT g.gene_symbol, o.orthofinder_id FROM eukarya.genes AS g JOIN annotations.orthofinder AS o ON g.gene_id=o.gene_id;

Этот запрос отлично работает с SQliteStudio, к которому прикреплены оба файла базы данных.

Код, который я сейчас использую для описания метаданных:

eukarya_engine = create_engine('sqlite:///eukarya_db.sqlite3')
annotations_engine = create_engine('sqlite:///eukarya_annotations_db.sqlite3')

meta = MetaData()  # This allows me to define cross database foreign keys

Eukarya = declarative_base(bind=eukarya_engine, metadata=meta)
Annotations = declarative_base(bind=annotations_engine, metadata=meta)
# I did the above in the hopes that by binding the engines this way,
# would percolate through the schema, and sqlalchemy would be able
# figure out which engine to use for each table.

class Genes(Eukarya):
  """SQLalchemy object representing the Genes table in the Eukarya database."""
  __tablename__ = 'genes'
  gene_id = Column(Integer, primary_key=True, unique=True)
  gene_symbol = Column(String(16), index=True)
  taxonomy_id = Column(Integer, ForeignKey(Species.taxonomy_id), index=True)
  original_gene_id = Column(String)

class Orthofinder(Annotations):
  """SQLalchemy object representing the Orthofinder table in the Annotations database."""
  __tablename__ = 'orthofinder'
  id = Column(Integer,primary_key=True, autoincrement=True)
  gene_id = Column(Integer, ForeignKey(Genes.gene_id), index=True)
  orthofinder_id = Column(String(10), index=True)

Session = sessionmaker()
session = Session(bind=eukarya_engine)

print(session.query(Genes.gene_symbol,Orthofinder.orthofinder_id).
      join(Orthofinder).all().statement)

Последний оператор печати возвращает:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: orthofinder [SQL: 'SELECT genes.gene_symbol AS genes_gene_symbol, orthofinder.orthofinder_id AS orthofinder_orthofinder_id \nFROM genes JOIN orthofinder ON genes.gene_id = orthofinder.gene_id']

Я считаю, что мои проблемы закончились, если я каким-то образом смогу привязать оба механизма баз данных к одному сеансу. Но как? Для двух баз данных, подключенных к одному движку (например, две базы данных в базе данных MySQL), я мог бы добавить __table_args__ = {'schema': 'annotations'} (согласно Перекрестное соединение базы данных в sqlalchemy), но я не могу понять это в случае SQLite.

Я бы предпочел решение, которое позволило бы пользователям моего кода создавать запросы, не зная, в какой базе данных находится каждая таблица.

Пожалуйста помоги! И заранее большое спасибо!


person John van Dam    schedule 03.11.2017    source источник
comment
По теме: stackoverflow.com/questions/23036751/, stackoverflow.com/questions/22289837/   -  person Ilja Everilä    schedule 03.11.2017
comment
Спасибо Илля! Я понял это. Странно, что ваша первая ссылка не попала в мои результаты поиска.   -  person John van Dam    schedule 03.11.2017


Ответы (1)


Ответ на мой вопрос (спасибо Илье за ​​решение):

Я могу определить двигатель так:

engine  = create_engine('sqlite://',echo=True)  # generate in mem database to attach mutitple sqlite databases to.
engine.execute("attach database 'eukarya_db.sqlite3' as eukarya;")
engine.execute("attach database 'eukarya_annotations_db.sqlite3' as annotations;")

А затем добавить

__table_args__ = {'schema': 'eukarya'}

or

__table_args__ = {'schema': 'annotations'}

К моим настольным классам.

Работает как шарм!

person John van Dam    schedule 03.11.2017