Настройка / вставка в базу данных "многие ко многим" с помощью Python, SQLALchemy, Sqlite
Я изучаю Python, и в качестве первого проекта Я принимаю Twitter RSS-каналы, анализируя данные и вставляя данные в базу данных sqlite. Я смог успешно проанализировать каждую запись фида в контент переменная (например, " вы должны купить низко..."), a URL-адресом переменная (например, u'http://bit.ly/HbFwL'), и a хэштегом список (например, #акции', u '#фондовый рынок', u '# финансы', u '#деньги', u'#mkt']). Я также был успешным в вставка этих трех частей информации в три отдельных столбца в таблице sqlite "RSSEntries", где каждая строка является другой записью/твитом rss.
тем не менее, я хочу настроить базу данных, где существует связь "многие ко многим" между отдельными записями RSS-канала (т. е. отдельными твитами) и хэштегами, связанными с каждой записью. Итак, я настроил следующие таблицы с помощью sqlalchemy (первая таблица просто включает URL-адреса RSS-каналов Twitterers, которые я хочу скачать и разобрать):
RSSFeeds = schema.Table('feeds', metadata,
schema.Column('id', types.Integer,
schema.Sequence('feeds_seq_id', optional=True), primary_key=True),
schema.Column('url', types.VARCHAR(1000), default=u''),
)
RSSEntries = schema.Table('entries', metadata,
schema.Column('id', types.Integer,
schema.Sequence('entries_seq_id', optional=True), primary_key=True),
schema.Column('feed_id', types.Integer, schema.ForeignKey('feeds.id')),
schema.Column('short_url', types.VARCHAR(1000), default=u''),
schema.Column('content', types.Text(), nullable=False),
schema.Column('hashtags', types.Unicode(255)),
)
tag_table = schema.Table('tag', metadata,
schema.Column('id', types.Integer,
schema.Sequence('tag_seq_id', optional=True), primary_key=True),
schema.Column('tagname', types.Unicode(20), nullable=False, unique=True)
)
entrytag_table = schema.Table('entrytag', metadata,
schema.Column('id', types.Integer,
schema.Sequence('entrytag_seq_id', optional=True), primary_key=True),
schema.Column('entryid', types.Integer, schema.ForeignKey('entries.id')),
schema.Column('tagid', types.Integer, schema.ForeignKey('tag.id')),
)
до сих пор мне удалось успешно ввести только три основные части информации в таблицу RSSEntries, используя следующий код (сокращенно where...)
engine = create_engine('sqlite:///test.sqlite', echo=True)
conn = engine.connect()
.........
conn.execute('INSERT INTO entries (feed_id, short_url, content, hashtags) VALUES
(?,?,?,?)', (id, tinyurl, content, hashtags))
теперь, вот огромный вопрос. Как вставить данные в feedtag и tagname таблицы? Это настоящий момент для меня, так как для начала hasthag переменная в настоящее время является списком, и каждая запись фида может содержать от 0 до, скажем, 6 хэштегов. Я знаю, как вставить весь список в один столбец, но не как вставить только элементы списка в отдельные столбцы (или, в этом примере, строки). Большим камнем преткновения является вопрос о том, как вставить отдельные хэштеги в tagname таблица, когда tagname может использоваться в многочисленных различных записях фида, а затем как правильно отображать "ассоциации" в feedtag таблица.
Короче, я точно знаю, как каждая из таблиц должна выглядеть, когда они все сделали, но я не знаю, как написать код, чтобы получить данные в tagname и feedtag таблицы. Вся эта установка "многие-ко-многим" для меня нова.
мне бы очень пригодилась твоя помощь. Заранее спасибо за любые предложения.
Грег
С. П. - редактировать - благодаря отличным предложениям Муравьев Aasma, Я был в состоянии почти заставить все это работать. В частности, 1-й и 2-й предлагаемые блоки кода теперь работают нормально, но у меня возникла проблема с реализацией 3-го блока кода. Я получаю следующую ошибку:
Traceback (most recent call last):
File "RSS_sqlalchemy.py", line 242, in <module>
store_feed_items(id, entries)
File "RSS_sqlalchemy.py", line 196, in store_feed_items
[{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags2])
NameError: global name 'entry_id' is not defined
затем, поскольку я не мог сказать, откуда муравьи Aasma получили часть" entry_id", я попытался заменить ее на " записи.id", думая, что это может вставить "id" из таблицы "записи". Тем не менее, в этом случае я получаю это ошибка:
Traceback (most recent call last):
File "RSS_sqlalchemy.py", line 242, in <module>
store_feed_items(id, entries)
File "RSS_sqlalchemy.py", line 196, in store_feed_items
[{'feedid': entries.id, 'tagid': tag_ids[tag]} for tag in hashtags2])
AttributeError: 'list' object has no attribute 'id'
Я не совсем уверен, где проблема, и я действительно не понимаю, где вписывается часть "entry_id", поэтому я вставил ниже весь мой соответствующий код "вставки". Кто-нибудь может помочь мне понять, что случилось? Обратите внимание, что я также только что заметил, что я неправильно называл свою последнюю таблицу "feedtag_table" вместо "entrytag_table", это не соответствовало моей изначально заявленной цели связывания индивидуального корма записи в хэштеги, а не в каналы хештеги. С тех пор я исправил код выше.
feeds = conn.execute('SELECT id, url FROM feeds').fetchall()
def store_feed_items(id, items):
""" Takes a feed_id and a list of items and stored them in the DB """
for entry in items:
conn.execute('SELECT id from entries WHERE short_url=?', (entry.link,))
s = unicode(entry.summary)
test = s.split()
tinyurl2 = [i for i in test if i.startswith('http://')]
hashtags2 = [i for i in s.split() if i.startswith('#')]
content2 = ' '.join(i for i in s.split() if i not in tinyurl2+hashtags2)
content = unicode(content2)
tinyurl = unicode(tinyurl2)
hashtags = unicode (hashtags2)
date = strftime("%Y-%m-%d %H:%M:%S",entry.updated_parsed)
conn.execute(RSSEntries.insert(), {'feed_id': id, 'short_url': tinyurl,
'content': content, 'hashtags': hashtags, 'date': date})
tags = tag_table
tag_id_query = select([tags.c.tagname, tags.c.id], tags.c.tagname.in_(hashtags))
tag_ids = dict(conn.execute(tag_id_query).fetchall())
for tag in hashtags:
if tag not in tag_ids:
result = conn.execute(tags.insert(), {'tagname': tag})
tag_ids[tag] = result.last_inserted_ids()[0]
conn.execute(entrytag_table.insert(),
[{'feedid': id, 'tagid': tag_ids[tag]} for tag in hashtags2])
1 ответов
во-первых, вы должны использовать SQLAlchemy SQL builder для вставок, чтобы дать SQLAlcehemy больше информации о том, что вы делаете.
result = conn.execute(RSSEntries.insert(), {'feed_id': id, 'short_url': tinyurl,
'content': content, 'hashtags': hashtags, 'date': date})
entry_id = result.last_insert_ids()[0]
чтобы вставить ассоциации тегов в схему, вам нужно кулак искать идентификаторы тегов и создавать любые, которые не существуют:
tags = tag_table
tag_id_query = select([tags.c.tagname, tags.c.id], tags.c.tagname.in_(hashtags))
tag_ids = dict(conn.execute(tag_id_query).fetchall())
for tag in hashtags:
if tag not in tag_ids:
result = conn.execute(tags.insert(), {'tagname': tag})
tag_ids[tag] = result.last_inserted_ids()[0]
затем просто вставьте связанный идентификатор в feedtag_table
. Вы можете использовать поддержку executemany, передав список диктов в метод execute.
conn.execute(feedtag_table.insert(),
[{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags])