使用 SQLAlchemy 插入计算值会给出 ProgrammingError
Inserting a calculated value with SQLAlchemy gives ProgrammingError
我有一个 table search
,其列 vector
类型为 tsvector
。我想使用 SQLAlchemy 核心 API 来插入行。计算 vector
需要 1) 在 Python 中进行一些处理和 2) 调用 to_tsvector
(一个 PG 函数)。
我正在弄乱 conn.execute(insert(Search), [{'vector': func.to_tsvector('here is a string')}])
但我得到了
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Function'
我正在尝试复制 SQL 查询 insert into search(vector) values (to_tsvector('here is a string'))
。
这对我来说很奇怪,我认为这是一个错误,但它不是错误。 zzzeek 在此讨论中对此进行了解释:
https://github.com/sqlalchemy/sqlalchemy/discussions/7640
您需要使用
insert().values()
喜欢 session.execute(tbl.insert().values(values))
而不是直接使用 session.execute(tbl.insert(), values)
.
万一它丢失了,你可以像这个例子一样执行插入:
代码
from sqlalchemy import (
create_engine,
Integer,
Text,
DateTime,
)
from sqlalchemy.schema import (
Column,
MetaData,
)
from sqlalchemy.sql import func, not_
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.exc import ProgrammingError
metadata = MetaData()
Base = declarative_base(metadata=metadata)
engine = create_engine('postgresql+psycopg2://username:password@/database', echo=False)
class Doc(Base):
__tablename__ = "docs"
id = Column(Integer, primary_key=True, index=True)
text = Column(Text, nullable=True)
vector = Column(TSVECTOR, nullable=True)
created_on = Column(DateTime, nullable=False)
metadata.create_all(engine)
doc_specs = [{
"text": "Frog jumping.",
}, {
"text": "Fish swimming.",
}, {
"text": "Bird flying.",
}, {
"text": "Cat jumping and flying.",
}]
with Session(engine) as session:
values = [{
"created_on": func.now(),
"text": spec["text"],
"vector": func.to_tsvector(spec["text"])
} for spec in doc_specs]
session.execute(Doc.__table__.insert().values(values))
session.commit()
print ("Matches")
for doc in session.query(Doc).filter(Doc.vector.match("jumping & flying")):
print (doc.id, doc.text, doc.vector)
print ("Misses")
for doc in session.query(Doc).filter(~Doc.vector.match("jumping & flying")):
print (doc.id, doc.text, doc.vector)
输出
DROP DATABASE
CREATE DATABASE
Matches
4 Cat jumping and flying. 'cat':1 'fli':4 'jump':2
Misses
1 Frog jumping. 'frog':1 'jump':2
2 Fish swimming. 'fish':1 'swim':2
3 Bird flying. 'bird':1 'fli':2
我有一个 table search
,其列 vector
类型为 tsvector
。我想使用 SQLAlchemy 核心 API 来插入行。计算 vector
需要 1) 在 Python 中进行一些处理和 2) 调用 to_tsvector
(一个 PG 函数)。
我正在弄乱 conn.execute(insert(Search), [{'vector': func.to_tsvector('here is a string')}])
但我得到了
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Function'
我正在尝试复制 SQL 查询 insert into search(vector) values (to_tsvector('here is a string'))
。
这对我来说很奇怪,我认为这是一个错误,但它不是错误。 zzzeek 在此讨论中对此进行了解释:
https://github.com/sqlalchemy/sqlalchemy/discussions/7640
您需要使用
insert().values()
喜欢 session.execute(tbl.insert().values(values))
而不是直接使用 session.execute(tbl.insert(), values)
.
万一它丢失了,你可以像这个例子一样执行插入:
代码
from sqlalchemy import (
create_engine,
Integer,
Text,
DateTime,
)
from sqlalchemy.schema import (
Column,
MetaData,
)
from sqlalchemy.sql import func, not_
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy.exc import ProgrammingError
metadata = MetaData()
Base = declarative_base(metadata=metadata)
engine = create_engine('postgresql+psycopg2://username:password@/database', echo=False)
class Doc(Base):
__tablename__ = "docs"
id = Column(Integer, primary_key=True, index=True)
text = Column(Text, nullable=True)
vector = Column(TSVECTOR, nullable=True)
created_on = Column(DateTime, nullable=False)
metadata.create_all(engine)
doc_specs = [{
"text": "Frog jumping.",
}, {
"text": "Fish swimming.",
}, {
"text": "Bird flying.",
}, {
"text": "Cat jumping and flying.",
}]
with Session(engine) as session:
values = [{
"created_on": func.now(),
"text": spec["text"],
"vector": func.to_tsvector(spec["text"])
} for spec in doc_specs]
session.execute(Doc.__table__.insert().values(values))
session.commit()
print ("Matches")
for doc in session.query(Doc).filter(Doc.vector.match("jumping & flying")):
print (doc.id, doc.text, doc.vector)
print ("Misses")
for doc in session.query(Doc).filter(~Doc.vector.match("jumping & flying")):
print (doc.id, doc.text, doc.vector)
输出
DROP DATABASE
CREATE DATABASE
Matches
4 Cat jumping and flying. 'cat':1 'fli':4 'jump':2
Misses
1 Frog jumping. 'frog':1 'jump':2
2 Fish swimming. 'fish':1 'swim':2
3 Bird flying. 'bird':1 'fli':2