简体   繁体   中英

Inserting a calculated value with SQLAlchemy

I have a table search with a column vector of type tsvector . I'd like to use the SQLAlchemy core API to insert rows. Computing vector requires 1) some processing in Python and 2) a call to to_tsvector (a PG function). Any tricks to doing this?

I'm messing around with conn.execute(insert(Search), [{'vector': func.to_tsvector('here is a string')}]) but am getting sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Function'

Edit - so the sql I'm trying to replicate is insert into search(vector) values (to_tsvector('here is a string'))

This seemed weird to me and I thought it was a bug. zzzeek explains it in this discussion:

https://github.com/sqlalchemy/sqlalchemy/discussions/7640

You need to use insert().values() like session.execute(tbl.insert().values(values)) instead of directly using session.execute(tbl.insert(), values) .

In case this gets lost you can perform the inserts like this example:

Code

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)

Output

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM