SQLAlchemy 테이블 관계

데이터 구동에 의존하는 지능과 통찰력의 회사로서 4Degrees는 자연히 복잡한 데이터베이스를 가지고 있다.previous post에서 우리는 SQLAlchemy 입문 안내서를 제공하여 신입 인턴과 직원들이SQLAlchemy ORM의 기초 지식을 이해하도록 돕는다.
이 글에서 우리는 이러한 이해를 바탕으로 여러 연결표를python 클래스에 어떻게 비추는지, 그리고 여러 테이블에 걸쳐 있는 데이터를 어떻게 조회하는지 깊이 있게 연구할 것이다.
관계
가장 흔히 볼 수 있는 표 관계를 1:n 관계라고 한다.예를 들어 user은 한 블로그에 발표할 수 있고 여러 개의 블로그 게시물이 user_blog_post표에 저장된다.이를 실현하기 위해, 우리는 두 개의python 클래스를 정의했고, 블로그 포스트 테이블에 user_id이라는 열을 추가했다. 이 테이블은 두 테이블 사이의 링크를 충당한다.
class user(db.Model):
      id = db.Column(db.Integer, primary_key=True)
      username = db.Column(db.String)
      email = db.Column(db.String)

class user_blog_post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    body = db.Column(db.String)
        user_id = db.Column(db.Integer)
똑똑한 독자는 기술적으로 말하자면 우리는 여기까지 할 수 있다는 것을 알아차릴 수 있을 것이다.우리는 두 개의 테이블과 이 두 개의 테이블을 연결하는 열이 있다.기술적으로는 옳지만 잘못된 공간도 있다.만약 우리가 의외로 존재하지 않는 사용자를 위해 user_blog_post표를 만들었다면?
이 문제를 해결하기 위해서, 우리는 표 관계를 정의할 때 사용하는 주요 도구인 ForeignKey를 소개했다.ForeignKey는 Column 객체가 적용한 매개변수로, 이 열의 값이 다른 테이블의 기존 값으로 구속되어야 함을 나타냅니다.본질적으로 만약에 우리가 두 표가 서로 관련되기를 원한다면 우리는 user_id이 존재하지 않는 기록을 인용하지 않도록 확보해야 한다.
user_id = db.Column(db.Integer, ForeignKey('user.id'))
만약 우리가 지금 user_blog_post 표에서 user_id을 사용하여 줄을 만들려고 시도하고 있는데 user 표의 id 값이 존재하지 않는다면 (예: 55) 오류가 발생하고 이 줄이 만들어지지 않을 것입니다.
psycopg2.errors.ForeignKeyViolation: insert or update on table "user_blog_post" violates foreign key constraint "user_blog_post_user_id_fkey"
DETAIL:  Key (user_id)=(55) is not present in table "user".
테이블에 ForeignKey가 존재한다는 것은 테이블 자체와 부모 테이블 사이에 다대일 관계가 있음을 의미한다.다시 말하면 만약에 우리가 제약을 받는 user_id값을 user_blog_post류에 두면 user류에 일치하는 id열이 존재해야 한다. 그러면 사용자마다 여러 개의 블로그 글이 있을 수 있지만 블로그 글마다 한 명의 사용자만 있을 수 있다.
이것은 SQLAlchemy에서 테이블 관계에 사용할 두 번째 유용한 도구를 가져왔습니다:db.relationship() 방법입니다.이런 방법이 정의표 관계에 진정으로 필요한 것은 아니라는 것을 이해하는 것이 중요하다.사실 앞에서 언급한 바와 같이 표 관계의 유일한 진정한 필요 항목은 두 표를 연결하는 열(즉 user_id)이다.
db야.relationship () 방법은ForeignKey 열을 이용하여 만든 은밀한 다대일 관계를 이용하여 이 두 테이블 사이의 링크를 비추는python 클래스에 공개합니다.
blog_posts = db.relationship("user_blog_post", backref='user')
이 줄을 user 클래스에 배치함으로써 SQLAlchemy ORM은python 환경에서 접근할 수 있는 user.blog_postsuser_blog_posts.user 속성을 구축했다.또한, 우리의python 환경은 다대일 관계를 이해한다.
newBlogPost = user_blog_post(title='first', body='first post body', user_id=1)
print(newBlogPost.user)
 None
newUser = user(username='Moshe', email='[email protected]')
print(newUser.blog_posts)
 [ ]
user표는 실제로blog post열이 없고 user_blog_post표는user열이 없습니다.이것은 다음 SQLAlchemy 코드와 출력된 SQL에서 잘 알 수 있습니다.
newUser = user(username='Moshe', email='[email protected]')
newUser.blog_posts = [
    user_blog_post(title='first', body='first post body'),
    user_blog_post(title='second', body='second post body')
]
db.session.add(newUser)
db.session.commit()

SQL
INSERT INTO user (username, email) VALUES (?, ?)
('Moshe', '[email protected]')
INSERT INTO user_blog_post (title, body, user_id) VALUES (?, ?, ?)
('first', 'first post body', 1)
INSERT INTO user_blog_post (title, body, user_id) VALUES (?, ?, ?)
('second', 'second post body', 1)
질의 테이블 관계
이제 우리는 새로운 테이블 관계를 어떻게 정의하는지 알고 한 연습에 깊이 들어가도록 했다. 이 연습은 여러 개의 관련 테이블을 뛰어넘어 조회하는 방법을 보여줄 것이다.만약 우리가 블로그 글을 쓴 모든 사용자에게 이메일을 보내고 싶다면, 이 블로그 글의 본문에는 '기계 학습' 이라는 단어가 포함되어 있다.그리고 우리는 그들에게 곧 거행될 기계 학습 회의에 참가하도록 초청할 것이다.우리는 어떻게 이 명단을 얻습니까?
우리가 필요로 하는 데이터는 email 표의 user이지만 우리가 선별해야 할 데이터는 body 표의 user_blog_post이다.이 점을 실현하기 위해서 우리는 조회를 사용할 수 있다.join() 방법:
theEmails = user.query.with_entities(user.email).join(user_blog_post).\
    filter(user_blog_post.body.like('%machine learning%')).all()
흥미로운 것은 SQLAlchemy ORM은 useruser_blog_post표를 어떻게 연결하는지 은밀하게 알고 있다. 왜냐하면 그들 사이에는 외부 키만 있기 때문이다.더 복잡한 상황에서는 그렇지 않습니다. 우리는 키 관계를 명확하게 설명할 것입니다.
theEmails = user.query.with_entities(user.email).join(user_blog_post, user.id == user_blog_post.user_id).filter(user_blog_post.body.like('%machine learning%')).all()

좋은 웹페이지 즐겨찾기