SQLAlchemy中的contains
操作只接受一个Model
对象而不是对象列表。如果我想创建一个接受包含任何一组对象的过滤器,那么使用包含并将它们与union
组合来创建多个过滤器是否有更多SQL风格的方式?
例如,请参阅以下代码:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(100))
son = db.relationship('Son', backref = 'parent', lazy = 'dynamic')
def __repr__(self):
return '<"%s">' % self.name
class Son(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(1000))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<"%s">' % self.name
db.create_all()
son1 = Son(name = '1 a 1')
son2 = Son(name = '1 b 1')
son3 = Son(name = '1 c 1')
son4 = Son(name = '2 a 2')
son5 = Son(name = '2 b 2')
user0 = User(name = 'w1')
user1 = User(name = 'w2')
user2 = User(name = 'w3')
user0.son.append(son1)
user0.son.append(son2)
user1.son.append(son3)
user1.son.append(son4)
user2.son.append(son5)
db.session.add(son1)
db.session.add(son2)
db.session.add(son3)
db.session.add(son4)
db.session.add(son5)
db.session.add(user0)
db.session.add(user1)
db.session.add(user2)
db.session.commit()
son_query = Son.query.filter(Son.name.ilike('%a%'))
son_query_all = son_query.all()
print son_query.all()
user_query = User.query.filter(User.son.contains(son_query_all[0])).union(*[User.query.filter(User.son.contains(query)) for query in son_query_all[1:]])
print user_query.all()
该示例首先创建两个模型:User
和Son
,然后创建3个User
个实例和5个Son
个实例。 user0
包含son1
和son2
,user1
包含son3
和son4
,user2
包含son5
。请注意,son1
和son4
的名称都与%a%
类似。现在,我想选择包含名称为User
的{{1}}个实例的所有Son
个实例。
当前方法是选择%a%
中的所有Son
个实例,然后选择包含各个所需son_query_all
个实例的User
个实例,然后使用{组合选择结果{1}}。 SQLAlchemy是否有更多SQL风格的方式来选择相同的方式?例如,是否有类似Son
的内容,以便最后一个查询可以更改为
union
请注意,我当然可以使用contains_any
和user_query = User.query.filter(User.son.contains_any(son_query_all))
操作为同一目的定义自定义contains_any
函数。我的问题是,是否有一种更有效的方式而不仅仅是union
所有contains
- ed?
答案 0 :(得分:1)
解决此类过滤的正确方法是使用JOIN
。基本上,您将Son
表加入User
表并按加入的实体字段进行过滤。
在SQLAlchemy中,您可以这样表达:
User.query.join(Son).filter(Son.name.ilike('%a%'))
它将生成以下SQL:
SELECT * FROM user
JOIN son ON user.id = son.user_id
WHERE lower(son.name) LIKE lower('%a%')