如何使用MSQLAlchemy(Postgres)(Python)中的联接进行复合循环查询

时间:2018-12-07 12:46:50

标签: python postgresql flask flask-sqlalchemy

好吧,请耐心等待,因为我是SQLAlchemy和Postgres的新手。我有以下模型:Lead,Keyword和User。

我已经在潜在客户和关键字之间建立了许多联系,如下所示:

keyword_identifier = db.Table(
    'keyword_identifier',
    db.Column('lead_id', db.Integer, db.ForeignKey('leads.id')),
    db.Column('keyword_id', db.Integer, db.ForeignKey('keywords.id'))
)

在我的用户中,我有一个称为关键字的属性,它是一个包含关键字id的数组。

现在,我需要找到与user.keywords列表中存在的关键字ID相关联的所有线索。

我尝试了以下方法:

leads = Lead.query.join(keyword_identifier).join(Keyword).filter(keyword_identifier.c.lead_id.in_([k for k in u.keywords]))

其中只有2个结果(我知道只有一个关键字与2000多个潜在客户相关联,因此绝对不正确)。

我也尝试过:

for keyword_id in user.keywords:
    leads = Lead.query.join(keyword_identifier).join(Keyword).filter(keyword_identifier.c.lead_id == keyword_id)

但这也不能带来正确的结果。

有人可以推荐这里最好的方法吗?

1 个答案:

答案 0 :(得分:1)

我修改了一个具有相同数据库布局的迷你示例:一本书连接到一个用户(一对多),一本书有很多单词,单词可以出现在多本书中(很多)。要获取与用户连接的所有图书的所有单词,请使用以下查询:

Word.query.join(Word, Book.words).filter(Book.user_id==1).all()

因此,将其翻译为您的示例,就像:

Lead.query.join(Lead, Keyword.leads).filter(Keyword.user_id==1234).all()

完整示例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy, BaseQuery

app = Flask(__name__)
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    books = db.relationship('Book', backref='user')

class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    words = db.relationship('Word', secondary='book_to_word_junction', lazy='subquery',
        backref=db.backref('book', lazy=True))

class Word(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

keyword_identifier = db.Table(
    'book_to_word_junction',
    db.Column('book_id', db.Integer, db.ForeignKey('book.id')),
    db.Column('word_id', db.Integer, db.ForeignKey('word.id'))
)

db.create_all()

def add_db_samples():
    dummy_data = {
        'user1@email.com': {
            'harry potter': ['yer', 'a', 'wizard', 'herry', 'no', 'way', 'hagrid'],
            'egg cookbook': ['a', 'recipe', 'for', 'scrambled', 'eggs', 'no', 'really', 'yummy', 'eggs']
        },
        'user2@email.com': {
            'da vinci code': ['some', 'action', 'some', 'romance']
        }
    }


    for email in dummy_data:
        user = User()
        for title in dummy_data[email]:
            book = Book(title=title)
            for word_name in dummy_data[email][title]:
                word = Word.query.filter_by(name=word_name).first()
                if not word:
                    word = Word(name=word_name)
                book.words.append(word)
                db.session.add(word)
                db.session.commit()
            user.books.append(book)
        db.session.add(user)
    db.session.commit()

add_db_samples()

print(Word.query.join(Word, Book.words).filter(Book.user_id==1).all())

编辑:

关于您的评论,您可以像平常在过滤步骤中那样使用in_()

Word.query.join(Word, Book.words).filter(Book.user_id.in_([1,2])).all()

Lead.query.join(Lead, Keyword.leads).filter(Keyword.user_id.in_([1, 2])).all()