Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQLAlchemy:过滤多对一关系,其中一个对象具有包含特定值的列表_Python_Sqlalchemy_Flask Sqlalchemy - Fatal编程技术网

Python SQLAlchemy:过滤多对一关系,其中一个对象具有包含特定值的列表

Python SQLAlchemy:过滤多对一关系,其中一个对象具有包含特定值的列表,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我有一些这样的表格: class Genre(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), index=True) artist_id = db.Column(db.Integer, db.ForeignKey('artist.id')) class Song(db.Model): id = db.Column(db.Integer

我有一些这样的表格:

class Genre(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), index=True)
    artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'))

class Song(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), index=True)
    artist = db.relationship('Artist', uselist=False)
    artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'))

class Artist(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), index=True)
    genres = db.relationship('Genre')
    songs = db.relationship('Song')
所以基本上,歌曲只有一个艺术家。每个艺术家可以有多种风格

我试图得到任何一个艺术家的所有歌曲,他的流派列表包含一个特定名称的流派。我做了一些研究,发现了一些非常接近的东西:

Song.query.filter(Artist.genres.any(Genre.name.in_([genre_name_im_looking_for])))
这将是一种工作,但不是所有情况下。例如,上述声明还将返回所有具有“独立摇滚”类型的艺术家的歌曲。如何指定我不希望流派名称在值列表中,而是希望它是一个特定的值

Song.query.filter(Artist.genres.any(Genre.name='rock'))
也不可能,因为它是一个关键字表达式


有什么想法吗?

经过进一步的研究,我找到了解决这个问题的一种方法,尽管与我想要的有点不同

首先,为了获得所有包含特定流派的艺术家,我执行了:

artists = Artist.query.filter(
    Artist.genres.any(Genre.name.like('genre_name'))).all()
然后,我迭代了每个艺术家,并通过在过滤器中将艺术家用作关键字表达式来查询歌曲模型,如下所示:

for a in artist:
    most_common_genre_songs = Song.query.filter_by(artist=a).all()
我不确定是否有更有效的方法来打这个电话,或者用一行的方式(我打赌有),但现在,这就可以了。

使用此测试数据:

# Test Data
artists = [
    Artist(
        name='should match rock',
        genres=[Genre(name='rock'), Genre(name='pop')],
        songs=[Song(name='love'), Song(name='hate')]
    ),
    Artist(
        name='should NOT match',
        genres=[Genre(name='indie rock')],
        songs=[Song(name='elsewhere')]
    ),
]

db.session.add_all(artists)
db.session.commit()
下面的查询应满足您的要求:

q = Song.query.filter(Song.artist.has(Artist.genres.any(Genre.name == 'rock')))
assert len(q.all()) == 2

它不应该是
Song.query.filter(Artist.genres.any(Genre.name=='rock'))
?(比较而非赋值)@Wash是正确的,但即使是[rock]中的
也不应该真正匹配
独立摇滚
。也许你的
艺术家既有
摇滚
又有
独立摇滚
流派。@van是的,我认为两者都不应该匹配。我检查了我的数据库。。。这位艺术家没有摇滚乐,但有很多以“摇滚乐”为名的流派,比如“独立摇滚乐”。还是不明白为什么它是匹配的。@Wash谢谢,我稍后再试。通常可以使用表达式,比如Artist.query.filter_by(name='whatever'),所以我甚至没有考虑使用比较。对sqlalchemy这个行业还是新手。@van,我试过你的问题,但我仍然发现艺术家们的流派列表中有“独立摇滚”,但没有“摇滚”。我已经检查过了,这位艺术家没有两种风格。这正是我想要的,谢谢。快速提问,我还有另一个表,Users,它与歌曲有一对多的关系,我现在希望增加您建议的查询,以过滤属于特定用户的歌曲。此查询工作
Song.query.filter(Song.artist.has(artist.genres.any(Genre.name='Genre')).filter(Song.user==some\u user\u object)。all()
交换筛选器语句会对性能产生什么样的影响?我认为在任何现代RDBMS中都不会有任何性能差异。很好的解决方案。谢谢,@AlexF。