我正在为日文字符(汉字)创建一个简单的查找应用程序,用户可以使用任何可用信息搜索数据库。
汉字:
含义EN (1个kanji_id可以有多个具有不同含义的条目):
用户可以选择按“id”,“character”,“heisig6”,“kanjiorigin”或“含义”进行搜索,然后它应该返回所有这些字段中的所有信息。 (所有字段只返回1个结果,但含义除外,它可以返回多个结果)
join
- > outerjoin
(否则将找不到没有起源的信息)import sqlalchemy as sqla
import sqlalchemy.orm as sqlo
from tableclass import TableKanji, TableMeaningEN, TableMisc, TableOriginKanji # See tableclass.py
# Searches database with argument search method
class SearchDatabase():
def __init__(self):
#self.db_name = "sqlite:///Kanji_story.db"
self.engine = sqla.create_engine("sqlite:///Kanji.db", echo=True)
# Bind the engine to the metadata of the Base class so that the
# declaratives can be accessed through a DBSession instance
tc.sqla_base.metadata.bind = self.engine
# For making sessions to connect to db
self.db_session = sqlo.sessionmaker(bind=self.engine)
def retrieve(self, s_input, s_method):
# s_input: search input
# s_method: search method
print("\nRetrieving results with input: {} and method: {}".format(s_input, s_method))
data = [] # Data to return
# User searches on non-empty string
if s_input:
session = self.db_session()
# Find id in other table than Kanji
if s_method == 'meaning':
s_table = TableMeaningEN # 'MeaningEN'
elif s_method == 'okanji':
s_table = TableOriginKanji # 'OriginKanji'
else:
s_table = TableKanji # 'Kanji'
result = session.query(TableKanji).outerjoin(TableMeaningEN).outerjoin(
(TableOriginKanji, TableKanji.origin_kanji)
).filter(getattr(s_table, s_method) == s_input).all()
print("result: {}".format(result))
for r in result:
print("r: {}".format(r))
meanings = [m.meaning for m in r.meaning_en]
print(meanings)
# TODO transform into origin kanji's
origins = [str(o.okanji_id) for o in r.okanji_id]
print(origins)
data.append({'character': r.character, 'meanings': meanings,
'indexes': [r.id, r.heisig6, r.kanjiorigin], 'origins': origins})
session.close()
if not data:
data = [{'character': 'X', 'meanings': ['invalid', 'search', 'result']}]
return(data)
这是一个有效的查询吗?:result = session.query(TableKanji).join(TableMeaningEN).filter(getattr(s_table, s_method) == s_input).all()
(.join语句是必要的,因为否则例如session.query(TableKanji).filter(TableMeaningEN.meaning == 'love').all()
由于某种原因返回我数据库中的所有含义?所以这是正确查询或我的tableclass.py中的relationship()
未正确定义?
已修复(请参阅tableclass.py中的lambda:
)kanji = relationship("TableKanji", foreign_keys=[kanji_id], back_populates="OriginKanji")
< - 有什么问题?它给出了错误:
文件“/path/python3.5/site-packages/sqlalchemy/orm/mapper.py”,第1805行,在get_property中 “Mapper'%s'没有属性'%s'”%(自我,键))
sqlalchemy.exc.InvalidRequestError:Mapper'Mapper | TableKanji | Kanji'没有属性'OriginKanji'
import sqlalchemy as sqla
from sqlalchemy.orm import relationship
import sqlalchemy.ext.declarative as sqld
sqla_base = sqld.declarative_base()
class TableKanji(sqla_base):
__tablename__ = 'Kanji'
id = sqla.Column(sqla.Integer, primary_key=True)
character = sqla.Column(sqla.String, nullable=False)
radical = sqla.Column(sqla.Integer) # Can be defined as Boolean
heisig6 = sqla.Column(sqla.Integer, unique=True, nullable=True)
kanjiorigin = sqla.Column(sqla.Integer, unique=True, nullable=True)
cjk = sqla.Column(sqla.String, unique=True, nullable=True)
meaning_en = relationship("TableMeaningEN", back_populates="kanji") # backref="Kanji")
okanji_id = relationship("TableOriginKanji", foreign_keys=lambda: TableOriginKanji.kanji_id, back_populates="kanji")
class TableMeaningEN(sqla_base):
__tablename__ = 'MeaningEN'
kanji_id = sqla.Column(sqla.Integer, sqla.ForeignKey('Kanji.id'), primary_key=True)
meaning = sqla.Column(sqla.String, primary_key=True)
kanji = relationship("TableKanji", back_populates="meaning_en")
class TableOriginKanji(sqla_base):
__tablename__ = 'OriginKanji'
kanji_id = sqla.Column(sqla.Integer, sqla.ForeignKey('Kanji.id'), primary_key=True)
okanji_id = sqla.Column(sqla.Integer, sqla.ForeignKey('Kanji.id'), primary_key=True)
order = sqla.Column(sqla.Integer)
#okanji = relationship("TableKanji", foreign_keys=[kanji_id], backref="okanji")
kanji = relationship("TableKanji", foreign_keys=[kanji_id], back_populates="okanji_id")
答案 0 :(得分:1)
我们真的必须能够看到你的数据库模式给出真正的批评,但假设没有外键,你所说的基本上是你能做的最好的。
当你复杂的关系发生时,SQLAlchemy真的开始闪耀。例如,如果您正确设置了外键,则可以执行以下操作。
# Assuming kanji is a tc.tableMeaningEN.kanji_id object
kanji_meaning = kanji.meanings
这会将汉字的含义作为一个数组返回,而无需进一步查询。
你可以深入了解关系,所以我在这里链接文档。 http://docs.sqlalchemy.org/en/latest/orm/relationships.html
编辑:实际上,您根本不需要手动加入,SQLAlchemy会为您完成。
你的课程案例有误,但我不确定SQLAlchemy是否区分大小写。如果有效,那就继续前进。
如果查询表(self.session.query(User).filter(User.username == self.name).first()),则应该有一个表类型的对象(User here)。 / p>
因此,在您的情况下,单独查询TableKanji表将返回该类型的对象。
kanji_obj = session.query(TableKanji).filter(TableKanji.id == id).first()
# This will return an array of all meaning_ens that match the foreign key
meaning_arr = kanji_obj.meaning_en
# This will return a single meeting, just to show each member of the arr is of type TableMeaningEn
meaning_arr[0].meaning
我有一个项目使用了其中的一些功能,希望它有所帮助: https://github.com/ApolloFortyNine/SongSense 数据库声明(带关系):https://github.com/ApolloFortyNine/SongSense/blob/master/songsense/database.py 自动加入:https://github.com/ApolloFortyNine/SongSense/blob/master/songsense/getfriend.py#L134
我非常喜欢我的数据库结构,但至于其余部分,它非常糟糕。希望它仍然有用。