Nano Hash - криптовалюты, майнинг, программирование

Postgres - удалить данные для столбца, который не существует в INSERT

У меня есть ненадежный поток данных, который напрямую передается в базу данных postgres.

Поток в основном включает заданный набор имен столбцов, но в редких случаях может включать столбцы, которые не были определены ранее, что означает, что в этих редких случаях вставка в postgres прерывается.

Я ищу решение для вставки столбцов из фида при удалении любых столбцов, вызванных неопределенными именами столбцов.

Одним очевидным простым решением является ведение списка допустимых столбцов и удаление любых столбцов румян перед вставкой. И это сработает, но я надеюсь избежать этого, так как фид имеет очень жесткие параметры тайм-аута, и чем больше я изменяю данные перед отправкой в ​​базу данных, тем больше я рискую тайм-аутом. В настоящее время существует очень простой фрагмент Python, который создает команды вставки с данными как есть без какого-либо разбора:

cursor.execute('INSERT INTO {} ({}) VALUES ({});'.format(
    my_table_name,
    ", ".join(columns),
    ", ".join(data)
))

Мой вопрос: есть ли способ сделать это на лету на стороне postgres? Ака удалить данные для столбцов, которые ранее не были определены, вставляя остальные на лету?

Я видел похожую проблему здесь но, насколько я могу судить, это решение не работает для postgres. Если такого решения не существует, это по-прежнему полезная информация, и я могу вернуться к предварительному анализу данных, где это возможно.

Заранее спасибо!


  • Поскольку вы используете psycopg2, я бы использовал его модуль sql для построения запросов: psycopg.org/docs/ sql.html. Далее предполагается, что данные предоставляются в виде списка dicts. Затем я бы использовал sql.Placeholder для параметров. Включите в список столбцов только нужные столбцы. Тогда запрос будет игнорировать те элементы, у которых нет столбца, соответствующего именам параметров. 07.06.2020

Ответы:


1

Используя psycopg2, вы можете сделать следующее: Получить столбцы таблицы перед вставкой и отфильтровать ненужные столбцы:

import psycopg2
from psycopg2 import sql 
from psycopg2.extras import RealDictCursor


def fetchTableColumns(cur, table):
    sql = """
        select
            attname::varchar as "column",
            pg_type.typname::varchar as "type",
            pg_type.typcategory as "category",
            NULL as "parent",
            attnotnull as "null"
        FROM
            pg_attribute, pg_class, pg_type
        WHERE
            attrelid = pg_class.oid
            AND pg_attribute.attisdropped = False
            AND relname = %s
            AND attnum > 0
            AND atttypid = pg_type.oid
    """

    cur.execute(sql, (table, ))
    columns = [col['column'] for col in cur.fetchall()]
    print('Columns for table: %s are %s' % (table, columns))
    return columns


def insert(cur):
    table_name = 'accounts'
    values = {
        'username': 'foobar',
        'email': '[email protected]',
        'pwd': 'bar4000#',
        'birth': '01/01/2010',
        'country': 'France',
        'gender': 'm'
    }

    columns = fetchTableColumns(cur, table_name)
    filteredValues = {k: v for (k,v) in values.items() if k in columns}  # just keep the values that are named by the columns of the table.

    query = sql.SQL("insert into {} ({}) values ({})").format(
        sql.Identifier(table_name),
        sql.SQL(', ').join(map(sql.Identifier, filteredValues.keys())),
        sql.SQL(', ').join(sql.Placeholder() * len(filteredValues.keys())))

    print (cur.mogrify(query, list(filteredValues.values())).decode('utf-8'))



if __name__ == '__main__':
    repo_dbausername = 'mf_usr'
    repo_dbapassword = 'XYZ'
    repo_host = 'localhost'
    repo_port = '5959'

    con = psycopg2.connect(user=repo_dbausername,
          password=repo_dbapassword,
          host=repo_host,
          port=repo_port,
          database="mf")
    cur = con.cursor(cursor_factory=RealDictCursor)
    insert(cur)

Выход:

Columns for table: accounts are ['id', 'username', 'pwd', 'user_id', 'plid', 'email', 'last_login', 'ctime', 'parent', 'token', 'atime', 'stime', 'status']
insert into "accounts" ("username", "email", "pwd") values ('foobar', '[email protected]', 'bar4000#')
# as you can see birth, country, gender do not appear in the query.

Примечание. Ради скорости/производительности вы можете реализовать кеш для столбцов, возвращаемых fetchTableColumns, и периодически обновлять кеш.
Если вам нужно быстрее, вы можете написать хранимую процедуру, которая выполняет то же самое, но непосредственно в базе данных.

07.06.2020

2

Решил, что это может помочь показать пример. Изменено из документов psycopg2: https://www.psycopg.org/docs/sql.html

columns = ["col_1", "col_2", "col_3", "col_4"]
q2 = sql.SQL("insert into {} ({}) values ({})").format(
     sql.Identifier("some_table"), 
     sql.SQL(', ').join(map(sql.Identifier, columns)),
     sql.SQL(', ').join(map(sql.Placeholder, columns)))
print(q2.as_string(conn))
insert into "some_table" ("col_1", "col_2", "col_3", "col_4") values (%(col_1)s, %(col_2)s, %(col_3)s, %(col_4)s)
data_dict = {"col_1": 1, "col_2": 2, "col_3": 3, "col_4": 4, "col_a": "a", "col_5": 5}

При выполнении запроса «col_a» и «col_5» будут игнорироваться, так как для них нет заполнителя.

07.06.2020
  • Это по-прежнему является менее желательным решением, когда приходится анализировать и отлавливать плохие столбцы на стороне скрипта, а не на стороне базы данных. Но это приближает меня к тому, что мне нужно, так что спасибо за это! 07.06.2020
  • Я не слежу, все, что вам нужно отслеживать, это столбцы в таблице и использовать их для INSERT. С приведенным выше кодом любые несоответствующие столбцы будут игнорироваться. 07.06.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..