Python Sqlalchemy包含与join的空关系,并包含
我有两个模型记录和记录结果,就像这样Python Sqlalchemy包含与join的空关系,并包含,python,json,filter,sqlalchemy,relationship,Python,Json,Filter,Sqlalchemy,Relationship,我有两个模型记录和记录结果,就像这样 class Recording(Base): __tablename__ = 'recordings' id = Column(Integer, primary_key=True) filename = Column(String, nullable=False) language_id = Column(Integer, ForeignKey('languages.id'), nullable=False) la
class Recording(Base):
__tablename__ = 'recordings'
id = Column(Integer, primary_key=True)
filename = Column(String, nullable=False)
language_id = Column(Integer, ForeignKey('languages.id'), nullable=False)
language = relationship("Language", back_populates="recordings")
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
user = relationship("User", back_populates="recordings")
created_at = Column(DateTime, nullable=False, default=func.now())
updated_at = Column(DateTime, nullable=False,
default=func.now(), onupdate=func.now())
deletedd_at = Column(DateTime, nullable=True)
def __repr__(self):
return 'id: {}'.format(self.id)
User.recordings = relationship("Recording", order_by=Recording.id, back_populates="user")
Language.recordings = relationship("Recording", order_by=Recording.id, back_populates="language")
class RecordingResult(Base):
__tablename__ = 'recording_results'
id = Column(Integer, primary_key=True)
is_with_dictionary = Column(Boolean, default=False)
result = Column(String, nullable=True)
run_time = Column(Float, default=0.0)
recording_id = Column(Integer, ForeignKey('recordings.id'), nullable=False)
recording = relationship("Recording", back_populates="recording_results", lazy="joined")
speech_service_id = Column(Integer, ForeignKey('speech_services.id'), nullable=False)
speech_service = relationship("SpeechService", back_populates="recording_results")
created_at = Column(DateTime, nullable=False, default=func.now())
updated_at = Column(DateTime, nullable=False,
default=func.now(), onupdate=func.now())
deletedd_at = Column(DateTime, nullable=True)
def __repr__(self):
return 'id: {}'.format(self.id)
Recording.recording_results = relationship("RecordingResult", order_by="desc(RecordingResult.id)", back_populates="recording", lazy="joined")
SpeechService.recording_results = relationship("RecordingResult", order_by=RecordingResult.id, back_populates="speech_service")
我需要获得记录项的列表,这些记录项是不包含记录的结果,并且带有条件(recording.user\u id==id,recording.deletedd==None,RecordingResult.deletedd==None)
我使用了这个查询
db.session.query(Recording).filter(Recording.user_id == id, Recording.deletedd_at == None).order_by(Recording.id.desc()).join(Recording.recording_results).options(contains_eager(Recording.recording_results)).filter(RecordingResult.deletedd_at == None).all()
它会过滤掉,但连接方法似乎不包括记录为空的录制结果关系
我使用棉花糖将结果打印到json
我的结果是:
{
"id": 4,
"filename": "15615378415768423_test.txt",
"language_id": 1,
"user_id": 2,
"recording_results": [
{
"id": 5,
"is_with_dictionary": true,
"result": "test5",
"run_time": 1200.2,
"recording_id": 4,
"speech_service_id": 2
}
],
"created_at": "2019-06-26T08:30:41.591410+00:00"
},
{
"id": 2,
"filename": "15615371606083994_test.txt",
"language_id": 2,
"user_id": 2,
"recording_results": [
{
"id": 1,
"is_with_dictionary": true,
"result": "test1",
"run_time": 1500.2,
"recording_id": 2,
"speech_service_id": 4
},
{
"id": 2,
"is_with_dictionary": false,
"result": "test2",
"run_time": 1600.2,
"recording_id": 2,
"speech_service_id": 3
}
],
"created_at": "2019-06-26T08:19:20.628205+00:00"
}
预期结果:
{
"id": 5,
"filename": "15616009750201173_test.txt",
"language_id": 1,
"user_id": 2,
"recording_results": [],
"created_at": "2019-06-27T02:02:55.035810+00:00"
},
{
"id": 4,
"filename": "15615378415768423_test.txt",
"language_id": 1,
"user_id": 2,
"recording_results": [
{
"id": 5,
"is_with_dictionary": true,
"result": "test5",
"run_time": 1200.2,
"recording_id": 4,
"speech_service_id": 2
}
],
"created_at": "2019-06-26T08:30:41.591410+00:00"
},
{
"id": 2,
"filename": "15615371606083994_test.txt",
"language_id": 2,
"user_id": 2,
"recording_results": [
{
"id": 2,
"is_with_dictionary": false,
"result": "test2",
"run_time": 1600.2,
"recording_id": 2,
"speech_service_id": 3
},
{
"id": 1,
"is_with_dictionary": true,
"result": "test1",
"run_time": 1500.2,
"recording_id": 2,
"speech_service_id": 4
}
],
"created_at": "2019-06-26T08:19:20.628205+00:00"
}
如何在联接查询中也包含空关系?一个
内部联接,如
join(Recording.recording_results)
仅当联接的两侧都存在匹配行时,才会生成一行
由Query.outerjoin()
生成的LEFT[OUTER]联接将包括左侧没有匹配行的行,因此如果没有使用右侧表的其他谓词,则更改联接类型会有所帮助
事实上是这样的,但它有点“正常工作”,因为它是一个为NULL的检查。不过,在这种情况下,它的适当位置是
ON
子句:
outerjoin(RecordingResult, and_(Recording.recording_results, RecordingResult.deletedd_at == None))
它取代了使用filter()
我得到了sqlalchemy.exc.ArgumentError:预期的映射实体或可选的/table作为连接目标错误,为什么它不将记录结果重分类为连接映射?嗯,稍后将查看发生的情况。是的,错误仅显示在使用on子句的示例中。如果我将join更改为outerjoin only,则它将工作。如果使用显式on
子句,则目标应该是错误所述的-RecordingResult
。