У меня есть веб-сканер, который будет вставлять ссылки в одну из двух таблиц в базе данных PostgreSQL, в зависимости от того, существует ли запись в третьей таблице.
Таблицы определяются с использованием SQLAlchemy следующим образом:
class Links(Base):
"""table of document --> document links between visited pages"""
__tablename__ = 'links'
id = Column(Integer, primary_key = True)
source = Column(Integer, ForeignKey("pages.id"), nullable=False)
target = Column(Integer, ForeignKey("pages.id"), nullable=False)
def __init__(self, source, target):
self.source = source
self.target = target
class URLFrontier(Base):
"""table of document --> URL links, from pages we've indexed to
those we haven't seen yet"""
__tablename__ = 'url_frontier'
id = Column(Integer, primary_key = True)
source = Column(Integer, ForeignKey("pages.id"), nullable=False)
target = Column(String, nullable=False)
def __init__(self, source, target):
self.source = source
self.target = target
class Page(Base):
"""A text document from a specific URL. Stores downloaded text content from web pages, and indexes for full-text search"""
__tablename__ = 'pages'
id = Column(Integer, primary_key = True)
url = Column(String)
title = Column(String)
text = Column(String)
last_visit = Column(DateTime)
word_positions = Column(TSVECTOR)
def __init__(self, url, title, text, last_visit):
self.url = url
self.title = title
self.text = text
self.last_visit = last_visit
self.word_positions = func.to_tsvector('simple', text)
Учитывая пару URL-адресов, (source_url, target_url)
, я пытаюсь найти эффективный и безопасный для потоков способ:
проверить, существует ли запись в таблице pages
, где поле url
== target_url
, если оносуществует, я хочу вставить (source, target)
в таблицу links
с URL-адресами, сопоставленными с правильными идентификаторами source
и target
, на основе сопоставления URL-адреса с полем id
в таблице pages
.
если его не существует, я хочу вставить (source, target)
в таблицу url_frontier
, с source
, сопоставленным с правильными id
из pages
и гдеtarget
просто вставляется в виде строки URL. **
Я пытался сделать это разными способами, например, просто выполнить запрос SELECT
, чтобы проверить,запись существует, а затем следует запрос INSERT
в соответствующую таблицу, но это не является потокобезопасным (поскольку данные могут быть изменены другим потоком в диапазоне от SELECT
до INSERT
).Другой вариант, который я изучал, - это использование UPDATE ... ON CONFLICT
, но, похоже, я не могу использовать его для вставки в другую таблицу, или, если это возможно, я не могу понять, как это сделать из документации.Как я могу INSERT INTO links
, если target
существует в pages
, и вставить в url_frontier
в противном случае?