如何将行ID映射到外部CSV文件?
我有一个包含地址信息的csv文件,里面有:zip
(邮政编码)、city
(城市)、state
(州)、country
(国家)、street
(街道)和house_no
(门牌号)。这些信息是通过OpenERP的导入界面导入的。你可以通过提供三种方式中的一种来导入相关数据:name
(名称)、database id
(数据库ID)或external id
(外部ID)。最简单的方式是提供name
。
举个例子,对于城市,我不需要特别提供它的ID(也不需要把列名从street
改成street_id
),只需要提供它的真实名称,比如Some city
。如果这个城市名称在city
表中存在,那么所有数据就会顺利导入。
但当有多个城市同名时,就会出现问题。这时我需要特别提供这些城市的ID来解决名称冲突。不过问题是,地址数量太多,几乎不可能逐个查看并手动更改名称为ID。
所以我在想,是否可以写个脚本,或者把这个csv文件传给PostgreSQL(或者通过OpenERP使用ORM),作为条件返回与csv文件条件匹配的ID列表。
在我的数据库中,street
表和city
表已经导入了所有需要的街道和城市。
city
表的结构是这样的(附带示例数据):
id| name| state_id|
1 | City1| 1
2 | City1| 2
3 | City2| 2|
state
表的示例:
id| name|
1 | State1
2 | State2
所以你可以看到,相同的名称可以通过它们的ID、州ID或州名来区分,如果你去state
表查看的话。
还有一个地址的csv文件示例(数据库中也有一个表来导入这些信息):
|zip| city | state_id| country | street| house_no
123 | City1| 1 | Country1| Street1| 25a
124 | City1| 2 | Country1| Street2| 34
125 | City2| 2
如果我通过OpenERP界面验证这样的csv文件,我会收到警告,提示有两个城市同名。如果我继续操作,系统会选择第一个导入到数据库中的城市,这样一些地址就会被错误地分配到不正确的州(要记住,城市这一列也用于各种村庄等,所以不同州可能会有相同的名称)。
因此,我需要将城市名称更改为它们的ID,但正如我所说的,数据行数有成千上万,手动操作几乎是不可能的,而且会花费很多时间。
最后,我需要的是以某种方式将所有地址csv文件中的信息传入数据库,特别是传入city
表,并获取ID列表的返回结果。
例如,如果我输入(作为city
表的条件):
name | state_id|
City1| 1
City1| 2
City2| 2
City1| 1
它应该输出给我这个:
1
2
3
1
有没有人能建议我如何得到这样的结果?
1 个回答
我通过写这个脚本解决了这个问题:
# -*- encoding: utf-8 -*-
#!/usr/bin/python
import psycopg2
import csv
#Connect to database
conn = psycopg2.connect(database="db_name",
user="user", password="password", host="127.0.0.1", port="5432")
cur = conn.cursor()
#Get all cities ids and names with specific state
cur.execute("SELECT id, name from res_country_state_city WHERE state_id = 53")
rows = cur.fetchall()
rows_dict = {}
#Generate dict from data provided
for row in rows:
rows_dict[row[1]] = row[0]
#Check which name from cities-names.csv match with name in database
#(match returns that cities id
with open('cities-names.csv') as csvfile:
with open('cities-ids.csv', 'wb') as csvfile2:
reader = csv.reader(csvfile)
writer = csv.writer(csvfile2)
#create ids csv file and write ids that were matched
for row in reader:
if rows_dict.get(row[0]):
writer.writerow([rows_dict.get(row[0])])
conn.close()