SQLAlchemy и joins, у нас нет внешних ключей

предположим следующее в MySQL:

CREATE TABLE users (
  id integer auto_increment primary key,
  username varchar(30),
  active enum('N','Y'),
  created_on int(11),
  updated_on int(11),
  points int(10),
  // other fields
);

CREATE TABLE comments (
  id integer auto_increment primary key,
  user_id integer,
  forum_id integer,
  favorited integer,
  // other fields
);

обратите внимание, что в таблицы не добавляются никакие формальные ограничения внешнего ключа. Это то, что я унаследовал и не могу изменить в нашей текущей настройке. (Мы пересматриваем всю систему, но в то же время я должен работать с тем, что мне дали)

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

эффективно, я хотел бы сделать что-то вроде:

SELECT 
  u.username,
  c.forum_id,
  count(c.id)
FROM 
  users u
  JOIN comments c ON u.id=c.user_id
WHERE
  u.id = 1234
GROUP BY
  u.username,
  c.forum_id;

код у меня включает в себя следующие вещи:

mapper(Users, users, primary_key=[users.c.id],
    include_properties=['user_id', 'username', 'active', 'created_on',
        'updated_on', 'points'])
mapper(Comments, comments, primary_key=[comments.c.id],
    include_properties=['active', 'user_id', 'favorited', 'forum_id'])

j = join(users, comments)
mapper(UserComments, j, properties={'user_id': [users.c.id,
    comments.c.user_id]})

session = create_session()
query = session.query(UserComments).filter(users.cid == 1234)
rdata = run(query)
for row in rdata:
    print row

... что, конечно, не удается с:

sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships
between 'users' and 'comments'.

Я не уверен, как обойти это, когда у нас нет внешних ключей. Как еще я могу определить отношения? Я думал, что это часть вызова mapper ():

mapper(UserComments, j, properties={'user_id': [users.c.id, 
    comments.c.user_id]})

... но, очевидно, я неправильно прочитал документацию.

заранее спасибо за любую помощь.

1 ответов


у вас есть два варианта. Вы можете передать условие соединения в join вот так:

j = join(users, comments, onclause=users.c.id == commends.c.user_id)

если вы определяете это в терминах orm.relationship свойство, параметр ключевого слова будет primaryjoin вместо onclause.

Я предпочитаю просто врет. Сообщите SQLAlchemy, что есть внешний ключ, даже если его нет. 
comments = Table('comments', metadata,
    Column('id', Integer, primary_key=True),
    Column('user_id', Integer, ForeignKey('users.id')),
    ...
)

SQLAlchemy будет продолжаться, как если бы внешний ключ действительно присутствовал, даже хотя в базе данных этого нет. Конечно, вы можете столкнуться с проблемами, если будет нарушено подразумеваемое ограничение ключа foriegn (comments.user_id когда нет соответствующего users.id), но вы, вероятно, будете в беде в любом случае.