1import sqlalchemy as sa
2from sqlalchemy.dialects.postgresql import TSVECTOR
3
4
5class TSVectorType(sa.types.TypeDecorator):
6 """
7 .. note::
8
9 This type is PostgreSQL specific and is not supported by other
10 dialects.
11
12 Provides additional functionality for SQLAlchemy PostgreSQL dialect's
13 TSVECTOR_ type. This additional functionality includes:
14
15 * Vector concatenation
16 * regconfig constructor parameter which is applied to match function if no
17 postgresql_regconfig parameter is given
18 * Provides extensible base for extensions such as SQLAlchemy-Searchable_
19
20 .. _TSVECTOR:
21 https://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#full-text-search
22
23 .. _SQLAlchemy-Searchable:
24 https://www.github.com/kvesteri/sqlalchemy-searchable
25
26 ::
27
28 from sqlalchemy_utils import TSVectorType
29
30
31 class Article(Base):
32 __tablename__ = 'user'
33 id = sa.Column(sa.Integer, primary_key=True)
34 name = sa.Column(sa.String(100))
35 search_vector = sa.Column(TSVectorType)
36
37
38 # Find all articles whose name matches 'finland'
39 session.query(Article).filter(Article.search_vector.match('finland'))
40
41
42 TSVectorType also supports vector concatenation.
43
44 ::
45
46
47 class Article(Base):
48 __tablename__ = 'user'
49 id = sa.Column(sa.Integer, primary_key=True)
50 name = sa.Column(sa.String(100))
51 name_vector = sa.Column(TSVectorType)
52 content = sa.Column(sa.String)
53 content_vector = sa.Column(TSVectorType)
54
55 # Find all articles whose name or content matches 'finland'
56 session.query(Article).filter(
57 (Article.name_vector | Article.content_vector).match('finland')
58 )
59
60 You can configure TSVectorType to use a specific regconfig.
61 ::
62
63 class Article(Base):
64 __tablename__ = 'user'
65 id = sa.Column(sa.Integer, primary_key=True)
66 name = sa.Column(sa.String(100))
67 search_vector = sa.Column(
68 TSVectorType(regconfig='pg_catalog.simple')
69 )
70
71
72 Now expression such as::
73
74
75 Article.search_vector.match('finland')
76
77
78 Would be equivalent to SQL::
79
80
81 search_vector @@ to_tsquery('pg_catalog.simple', 'finland')
82
83 """
84
85 impl = TSVECTOR
86 cache_ok = True
87
88 class comparator_factory(TSVECTOR.Comparator):
89 def match(self, other, **kwargs):
90 if 'postgresql_regconfig' not in kwargs:
91 if 'regconfig' in self.type.options:
92 kwargs['postgresql_regconfig'] = self.type.options['regconfig']
93 return TSVECTOR.Comparator.match(self, other, **kwargs)
94
95 def __or__(self, other):
96 return self.op('||')(other)
97
98 def __init__(self, *args, **kwargs):
99 """
100 Initializes new TSVectorType
101
102 :param *args: list of column names
103 :param **kwargs: various other options for this TSVectorType
104 """
105 self.columns = args
106 self.options = kwargs
107 super().__init__()