Python SQL炼金术-在外键可能不存在时指定关系

Python SQL炼金术-在外键可能不存在时指定关系,python,sqlalchemy,foreign-keys,Python,Sqlalchemy,Foreign Keys,我需要在一个数据库中设置两个表,我正在努力决定如何在SQL Alchemy中设计这些表 表1包含原始地址数据和地址源。如果原始地址来自不同的来源,它们可能会出现多次 表2包含这些地址的地理编码版本。每个地址只显示一次。如果地址在表1中至少出现一次,则应仅在此表中出现 当新地址进入系统时,它们将首先插入表1。然后,我将有一个脚本,用于查找表1中不在表2中的记录,对它们进行地理编码并将它们插入表2中 我有以下代码: class RawAddress(Base): __tablename__

我需要在一个数据库中设置两个表,我正在努力决定如何在SQL Alchemy中设计这些表

表1包含原始地址数据和地址源。如果原始地址来自不同的来源,它们可能会出现多次

表2包含这些地址的地理编码版本。每个地址只显示一次。如果地址在表1中至少出现一次,则应仅在此表中出现

当新地址进入系统时,它们将首先插入表1。然后,我将有一个脚本,用于查找表1中不在表2中的记录,对它们进行地理编码并将它们插入表2中

我有以下代码:

class RawAddress(Base):
    __tablename__ = 'rawaddresses'

    id = Column(Integer,primary_key = True)
    source_of_address = Column(String(50))

    #Want something like a foreign key here, but address may not yet exist
    #in geocoded address table
    full_address = Column(String(400)) 


class GeocodedAddress(Base):
    __tablename__ = 'geocodedaddresses'

    full_address = Column(String(400), primary_key = True)
    lat = Column(Float)
    lng = Column(Float)
在SQL Alchemy中,有没有一种方法可以建立完整地址字段之间的关系?或者我的设计有误——也许每次我看到一个新的原始地址时,我都应该将它添加到GeocodedAddress表中,并用一个标志表示它是否是地理编码的


非常感谢您的帮助。

考虑到您的意见,允许此类数据存储以及插入/更新过程的代码应该可以完成这项工作。它面前的评论很少:

  • 外键可以为NULL,因此您的FK想法仍然有效
  • 您可以在任何模型上定义关系,并使用
    backref
代码:

现在:

# logic

def get_geo(full_address):
    " Dummy function which fakes `full_address` and get lat/lng using hash(). "
    hs = hash(full_address)
    return (hs >> 8) & 0xff, hs & 0xff


def add_test_data(addresses):
    with session.begin():
        for fa in addresses:
            session.add(RawAddress(full_address=fa))


def add_geo_info():
    with session.begin():
        q = (session
             .query(RawAddress)
             .filter(~RawAddress.geocoded_address.has())
             )
        for ra in q.all():
            print("Computing geo for: {}".format(ra))
            lat, lng = get_geo(ra.full_address)
            ra.geocoded_address = GeocodedAddress(
                full_address=ra.full_address, lat=lat, lng=lng)
以及一些测试:

# step-1: add some raw addresses
add_test_data(['Paris', 'somewhere in Nevada'])
print("-"*80)

# step-2: get those raw which do not have geo
add_geo_info()
print("-"*80)

# step-1: again with 1 new, 1 same
add_test_data(['Paris', 'somewhere in Chicago'])
print("-"*80)

# step-2: get those raw which do not have geo
add_geo_info()
print("-"*80)


# check: print all data for Paris geo:
gp = session.query(GeocodedAddress).filter(GeocodedAddress.full_address == 'Paris').one()
assert 2 == len(gp.raw_addresses)
print(gp.raw_addresses)

为什么不创建一个表,允许
lat
lng
null
,首先保存
完整地址
,虽然第二个过程将查找所有没有地理信息的人并进行更新?谢谢-这实际上是我目前正在使用的解决方案…很高兴知道这相当合理…另一个解决方案是在
GeocodedAddress
表上有一个
ForeignKey
,它将引用主键
RawAddress
表的(
id
)。通过这种方式,可以很容易地列出那些还没有
geocodeddress
RawAddress
实例,计算并插入它。请注意,在
字符串(400)上有一个
ForeignKey
并不好
列。我会使用id。如果有兴趣,请告诉我,我可以提供一个代码示例。谢谢。问题不在于一个地理编码地址可能与
RawAddress
表中的许多记录相关吗?例如,如果我们从两个不同的来源观察到相同的完整地址,它将在中出现两次ode>RawAddress表,但只应进行一次地理编码。。。
# step-1: add some raw addresses
add_test_data(['Paris', 'somewhere in Nevada'])
print("-"*80)

# step-2: get those raw which do not have geo
add_geo_info()
print("-"*80)

# step-1: again with 1 new, 1 same
add_test_data(['Paris', 'somewhere in Chicago'])
print("-"*80)

# step-2: get those raw which do not have geo
add_geo_info()
print("-"*80)


# check: print all data for Paris geo:
gp = session.query(GeocodedAddress).filter(GeocodedAddress.full_address == 'Paris').one()
assert 2 == len(gp.raw_addresses)
print(gp.raw_addresses)