33
44
55class IvfflatIndex (PostgresIndex ):
6+ """Django index class for the pgvector IVFFlat (Inverted File Flat) index type.
7+
8+ IVFFlat partitions vectors into *lists* (Voronoi cells) at build time and
9+ restricts each query to the *probes* nearest lists. It offers fast approximate
10+ nearest-neighbour search with a controllable recall/speed trade-off.
11+
12+ Build-time cost is proportional to ``lists``; query-time cost is proportional to
13+ ``probes`` (a session-level GUC, ``ivfflat.probes``, not an index parameter).
14+ The index **requires** the table to contain data before it is created — an empty
15+ table produces degenerate clusters.
16+
17+ Supported distance operators (set via ``opclasses``):
18+
19+ - ``vector_l2_ops`` — L2 / Euclidean distance (``<->``)
20+ - ``vector_ip_ops`` — inner product (``<#>``)
21+ - ``vector_cosine_ops`` — cosine distance (``<=>``)
22+ - ``halfvec_l2_ops`` / ``halfvec_ip_ops`` / ``halfvec_cosine_ops`` — half-precision variants
23+ - ``sparsevec_l2_ops`` / ``sparsevec_ip_ops`` / ``sparsevec_cosine_ops`` — sparse-vector variants
24+
25+ Example::
26+
27+ from pgvector.django import IvfflatIndex
28+
29+ class Meta:
30+ indexes = [
31+ IvfflatIndex(
32+ name='item_embedding_ivfflat',
33+ fields=['embedding'],
34+ lists=100,
35+ opclasses=['vector_cosine_ops'],
36+ )
37+ ]
38+
39+ See also: https://github.com/pgvector/pgvector#ivfflat
40+ """
41+
642 suffix = 'ivfflat'
743
844 def __init__ (self , * expressions : Any , lists : int | None = None , ** kwargs : Any ) -> None :
45+ """Create an IVFFlat index.
46+
47+ Args:
48+ *expressions: Column expressions to index (forwarded to
49+ :class:`~django.contrib.postgres.indexes.PostgresIndex`).
50+ lists: Number of lists (Voronoi cells) to partition the vector
51+ space into during index construction. Controls the
52+ accuracy/speed trade-off at *build* time.
53+
54+ - Higher values improve recall but increase build time and
55+ memory consumption.
56+ - As a rule of thumb pgvector recommends ``rows / 1000`` for
57+ up to 1 million rows, and ``sqrt(rows)`` beyond that.
58+ - Valid range: 1 – 32768. pgvector default: ``100``.
59+ - ``None`` omits the parameter and lets the server use its
60+ compiled-in default.
61+ **kwargs: Additional keyword arguments forwarded to
62+ :class:`~django.contrib.postgres.indexes.PostgresIndex`
63+ (e.g. ``name``, ``fields``, ``opclasses``, ``condition``).
64+ """
965 self .lists = lists
1066 super ().__init__ (* expressions , ** kwargs )
1167
1268 def deconstruct (self ) -> tuple [Any , Any , Any ]:
69+ """Return enough information to recreate the index via migrations.
70+
71+ Returns:
72+ A ``(path, args, kwargs)`` tuple as required by Django's
73+ deconstruction protocol. ``lists`` is included in *kwargs* only
74+ when it was explicitly set.
75+ """
1376 path , args , kwargs = super ().deconstruct ()
1477 if self .lists is not None :
1578 kwargs ['lists' ] = self .lists
1679 return path , args , kwargs
1780
1881 def get_with_params (self ) -> list [str ]:
82+ """Return the ``WITH (...)`` storage parameters for the ``CREATE INDEX`` DDL.
83+
84+ Returns:
85+ A list of ``'key = value'`` strings passed to the PostgreSQL
86+ ``WITH`` clause. Empty list when no parameters were specified.
87+ """
1988 with_params = []
2089 if self .lists is not None :
2190 with_params .append ('lists = %d' % self .lists )
2291 return with_params
2392
2493
2594class HnswIndex (PostgresIndex ):
95+ """Django index class for the pgvector HNSW (Hierarchical Navigable Small World) index type.
96+
97+ HNSW builds a multi-layer proximity graph over the vectors. It generally
98+ provides higher recall and faster queries than :class:`IvfflatIndex` at the
99+ cost of more memory and a longer build time. Unlike IVFFlat it can be built
100+ on an empty table and updated incrementally.
101+
102+ Query-time recall is tuned with ``hnsw.ef_search`` (a session-level GUC),
103+ not an index parameter.
104+
105+ Supported distance operators (set via ``opclasses``):
106+
107+ - ``vector_l2_ops`` — L2 / Euclidean distance (``<->``)
108+ - ``vector_ip_ops`` — inner product (``<#>``)
109+ - ``vector_cosine_ops`` — cosine distance (``<=>``)
110+ - ``vector_l1_ops`` — L1 / Manhattan distance (``<+>``)
111+ - ``halfvec_*`` / ``sparsevec_*`` variants are also available
112+
113+ Example::
114+
115+ from pgvector.django import HnswIndex
116+
117+ class Meta:
118+ indexes = [
119+ HnswIndex(
120+ name='item_embedding_hnsw',
121+ fields=['embedding'],
122+ m=16,
123+ ef_construction=64,
124+ opclasses=['vector_cosine_ops'],
125+ )
126+ ]
127+
128+ See also: https://github.com/pgvector/pgvector#hnsw
129+ """
130+
26131 suffix = 'hnsw'
27132
28- def __init__ (self , * expressions : Any , m : int | None = None , ef_construction : int | None = None , ** kwargs : Any ) -> None :
133+ def __init__ (
134+ self ,
135+ * expressions : Any ,
136+ m : int | None = None ,
137+ ef_construction : int | None = None ,
138+ ** kwargs : Any ,
139+ ) -> None :
140+ """Create an HNSW index.
141+
142+ Args:
143+ *expressions: Column expressions to index (forwarded to
144+ :class:`~django.contrib.postgres.indexes.PostgresIndex`).
145+ m: Maximum number of bidirectional links (edges) created for each
146+ new node during graph construction. Controls the graph
147+ connectivity at *build* time.
148+
149+ - Higher values yield better recall and faster queries but
150+ consume more memory (roughly ``m * 8`` bytes per vector per
151+ layer beyond the base layer).
152+ - Valid range: 2 – 100. pgvector default: ``16``.
153+ - ``None`` omits the parameter and lets the server use its
154+ compiled-in default.
155+ ef_construction: Size of the dynamic candidate list maintained
156+ while inserting a new vector into the graph. Controls the
157+ quality of the *build*-time graph structure.
158+
159+ - Higher values produce a denser, better-connected graph with
160+ improved recall, at the cost of a slower build.
161+ - Must satisfy ``ef_construction >= 2 * m``.
162+ - Valid range: 4 – 1000. pgvector default: ``64``.
163+ - ``None`` omits the parameter and lets the server use its
164+ compiled-in default.
165+ **kwargs: Additional keyword arguments forwarded to
166+ :class:`~django.contrib.postgres.indexes.PostgresIndex`
167+ (e.g. ``name``, ``fields``, ``opclasses``, ``condition``).
168+ """
29169 self .m = m
30170 self .ef_construction = ef_construction
31171 super ().__init__ (* expressions , ** kwargs )
32172
33173 def deconstruct (self ) -> tuple [Any , Any , Any ]:
174+ """Return enough information to recreate the index via migrations.
175+
176+ Returns:
177+ A ``(path, args, kwargs)`` tuple as required by Django's
178+ deconstruction protocol. ``m`` and ``ef_construction`` are
179+ included in *kwargs* only when they were explicitly set.
180+ """
34181 path , args , kwargs = super ().deconstruct ()
35182 if self .m is not None :
36183 kwargs ['m' ] = self .m
@@ -39,6 +186,12 @@ def deconstruct(self) -> tuple[Any, Any, Any]:
39186 return path , args , kwargs
40187
41188 def get_with_params (self ) -> list [str ]:
189+ """Return the ``WITH (...)`` storage parameters for the ``CREATE INDEX`` DDL.
190+
191+ Returns:
192+ A list of ``'key = value'`` strings passed to the PostgreSQL
193+ ``WITH`` clause. Empty list when no parameters were specified.
194+ """
42195 with_params = []
43196 if self .m is not None :
44197 with_params .append ('m = %d' % self .m )
0 commit comments