SQLAlchemy / PostgreSQL: как условно вставить данные в одну из двух таблиц, основываясь на том, существует ли запись в третьей таблице - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть веб-сканер, который будет вставлять ссылки в одну из двух таблиц в базе данных 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), я пытаюсь найти эффективный и безопасный для потоков способ:

  1. проверить, существует ли запись в таблице pages, где поле url == target_url

  2. , если оносуществует, я хочу вставить (source, target) в таблицу links с URL-адресами, сопоставленными с правильными идентификаторами source и target, на основе сопоставления URL-адреса с полем id в таблице pages.

  3. если его не существует, я хочу вставить (source, target) в таблицу url_frontier, с source, сопоставленным с правильными id из pages и гдеtarget просто вставляется в виде строки URL. **

Я пытался сделать это разными способами, например, просто выполнить запрос SELECT, чтобы проверить,запись существует, а затем следует запрос INSERT в соответствующую таблицу, но это не является потокобезопасным (поскольку данные могут быть изменены другим потоком в диапазоне от SELECT до INSERT).Другой вариант, который я изучал, - это использование UPDATE ... ON CONFLICT, но, похоже, я не могу использовать его для вставки в другую таблицу, или, если это возможно, я не могу понять, как это сделать из документации.Как я могу INSERT INTO links, если target существует в pages, и вставить в url_frontier в противном случае?

...