Mythosia.VectorDb.Postgres - Release Notes
v10.8.1
Changed
- Mixed vector/text
HybridSearchAsyncnow applies the configuredHnswIndexOptions.EfSearchorIvfFlatIndexOptions.Probeson the same connection and transaction as its search query, matching ordinary vector search. Previously, this path could use the database session defaults instead of the configured values. - Runtime vector settings remain transaction-local and do not leak into later pooled-connection queries. Text-only search does not apply vector index settings. Hybrid search retains its existing API and does not acquire a per-request
VectorSearchRuntimeOptionsoverride.
Internal
- Added three PostgreSQL integration cases covering HNSW with full-text/trigram search and IVFFlat settings observed inside the search transaction. All 167 vector-store tests pass, including these live PostgreSQL cases.
Compatibility
- No public API changes, schema migration or reindexing are required when upgrading from 10.8.0. Requires
Mythosia.VectorDb.Abstractions4.1.0, unchanged from 10.8.0. - Configured search breadth can improve recall, but approximate nearest-neighbor search and metadata filtering can still return fewer than
topKresults. This patch does not guarantee a full result count or enable iterative scanning.
v10.8.0
Added
- Text-only retrieval through
ITextSearchStoreand configurable normalized weighted RRF throughIConfigurableHybridSearchStore, with filters and cancellation on the active search legs.
Fixed
Trigram search now orders by
word_similarityand a stable record ID instead of using an invalid<%>ordering operator.Natural-language keyword queries such as
hello !no longer produce danglingtsqueryoperators; existing OR behavior is retained. Symbol distinctions such asC#versusC++still require a separate analyzer design.Empty
NotInconditions exclude records missing the metadata key, consistently with the shared filter contract.
v10.7.1
Changed
- Recompiled against
Mythosia.VectorDb.Abstractionsv4.0.1 (XML doc fixes). No code changes.
v10.7.0
Breaking Changes โ Schema
namespaceandscopecolumns removed โ all values are now stored in themetadataJSONB column.- Primary key changed from
(namespace, id)to(id). namespaceandscopecolumns no longer exist in the table schema.- Namespace/scope filtering uses the standard metadata JSONB operators (
metadata @> '{"namespace":"docs"}'::jsonb), leveraging the existing GIN index onmetadata. - Existing tables are migrated automatically on first operation.
- Primary key changed from
Changed
- Schema auto-provisioning โ
CreateSchemaAsyncnow creates tables withoutnamespace/scopecolumns and withPRIMARY KEY (id). - Automatic legacy schema migration โ regardless of
EnsureSchemasetting, the store detects the legacynamespacecolumn on first operation and automatically migrates the schema in a single transaction:- Merges
namespace/scopecolumn values intometadataJSONB. - Resolves duplicate IDs across namespaces by prefixing with
{namespace}:(e.g.,chunk-1in namespacedocsโdocs:chunk-1). Non-duplicate IDs are unchanged. - Changes the primary key from
(namespace, id)to(id). - Drops the
namespaceandscopecolumns. - Drops the
idx_ns_scopeindex.
- On failure, the transaction rolls back and the schema remains unchanged.
- Merges
- SQL simplification โ all query methods (
SearchAsync,HybridSearchAsync,GetAsync,GetBatchAsync,CountAsync,DeleteAsync,DeleteByFilterAsync,ReplaceByFilterAsync) no longer have special namespace/scope column handling. All conditions are processed uniformly via JSONB metadata filtering. BuildFilterWhereโ removedGetNonReservedConditions(namespace/scope bypass). AllVectorFilter.Where(...)conditions are now treated as standard metadata conditions.ReadRecordโ reads namespace/scope frommetadataJSONB directly (no column injection).- Hybrid search SQL โ RRF join key simplified from
(namespace, id)to(id).
Compatibility
- Requires
Mythosia.VectorDb.Abstractionsv4.0.0. - Fully automatic migration from v10.6.x โ no manual steps required.
v10.6.1
Changed
- Namespace filtering is now optional โ when
VectorFilter.Namespaceis null, theWHERE namespace = @nsclause is omitted entirely. Previously, a null namespace was silently replaced with"default", forcing every query to filter on the"default"namespace even when namespace partitioning was not in use.- Affected methods:
SearchAsync,HybridSearchAsync,GetAsync,GetBatchAsync,DeleteAsync,DeleteByFilterAsync,ReplaceByFilterAsync. BuildTextCandidatesCte(used byHybridSearchAsync) also updated to accept a conditional namespace clause.- Upsert unchanged โ
UpsertAsync/UpsertBatchAsyncstill fall back to"default"whenrecord.Namespaceis null because the DB column isNOT NULLand part of the primary key. CountAsyncwas already correct (no change needed).
- Affected methods:
Deprecated
VectorRecord.Namespace,VectorRecord.Scope,VectorFilter.Namespace,VectorFilter.Scope,VectorFilter.WithNamespace(),INamespaceContext,IScopeContext, andInNamespace()/InScope()are now marked[Obsolete].- These will be removed in a future major version.
- Use
Metadataentries (e.g.Metadata["namespace"]) andVectorFilter.Where("namespace", value)for logical isolation instead. - This aligns with industry-standard vector database designs (Qdrant payload, Pinecone metadata, LangChain PGVector).
Compatibility
- Backward compatible with v10.6.0. No schema changes. Existing records stored with namespace
"default"remain accessible. - Deprecated APIs still function but produce
CS0618compiler warnings.
v10.6.0
Breaking Changes
VectorFilter construction API changed (see Mythosia.VectorDb.Abstractions v3.0.0). Any code that builds a VectorFilter to pass to SearchAsync, HybridSearchAsync, GetAsync, GetBatchAsync, CountAsync, DeleteAsync, DeleteByFilterAsync, or ReplaceByFilterAsync must be updated:
// Before โ compile error in v10.6.0
store.SearchAsync(vector, filter: VectorFilter.ByMetadata("k", "v"));
store.CountAsync(new VectorFilter { MetadataMatch = new Dictionary<string, string> { ["k"] = "v" } });
// After
store.SearchAsync(vector, filter: new VectorFilter().Where("k", "v"));
store.CountAsync(new VectorFilter().Where("k", "v"));
Changed
- SQL filter builder โ rewrote
BuildFilterWhere/AppendConditionGroup/AppendMetadataConditionto support theVectorFilterfluent condition tree introduced inMythosia.VectorDb.Abstractionsv3.0.0.Eqโmetadata @> @val::jsonb(JSONB containment โ preserves GIN index).Neโmetadata->>@key != @valGt / Gte / Lt / Lteโmetadata->>@key > @val(lexicographic string comparison).Inโmetadata->>@key = ANY(@vals)(Npgsql array binding).NotInโNOT (metadata->>@key = ANY(@vals)).Likeโmetadata->>@key LIKE @val.Existsโjsonb_exists(metadata, @key).NotExistsโNOT jsonb_exists(metadata, @key).And / Orgroups โ wrapped in(...)withAND/ORjoins.- Key names are parameterized (
@mf_k{idx}) for all non-Eq operators. Values are always parameterized. No SQL injection surface.
CountAsyncโ updated toWHERE 1=1pattern, appending filter conditions viaBuildFilterWhere.
v10.5.0
Added
PostgresStore.GetBatchAsyncโ fetches multiple records in a single query usingWHERE id = ANY(@ids)with Npgsql array binding. Applies full filter conditions (namespace, scope, metadata) viaBuildFilterWhere.PostgresStore.CountAsyncโSELECT COUNT(*)with optionalWHEREclauses for namespace, scope, and metadata jsonb containment (@>). Returns the total record count when filter is null.
Changed
PostgresStore.GetAsyncโ now applies the full filter (scope, metadata) viaBuildFilterWherein addition to the existingnamespace = @ns AND id = @idcondition. Previously, only namespace was checked.PostgresStore.DeleteAsyncโ now applies the full filter (scope, metadata) viaBuildFilterWhere. Previously, only namespace was used in theWHEREclause.- Dependency updates:
Npgsqlโ 10.0.2,System.Text.Jsonโ 10.0.5.
Compatibility
- Fully backward compatible with v10.4.0. The
GetAsync/DeleteAsyncbehavior changes only affect callers that pass a scope or metadata filter; plain calls without a filter behave identically to before.
v10.4.0
Added
ReplaceByFilterAsynctransactional override โ wraps DELETE + INSERT in a single PostgreSQL transaction, eliminating the query gap that occurs when re-embedding modified files.- Heavy work (document loading, embedding generation) happens outside the transaction.
- Transaction scope covers only the DB I/O (DELETE by filter โ INSERT new records), minimizing lock duration.
- On failure, the transaction rolls back and existing vectors remain intact.
Compatibility
- Fully backward compatible with v10.3.0. No breaking changes โ overrides the default interface method from Abstractions v2.3.0.
v10.3.0
Added
VerifyConnectionAsyncโ opens a real TCP connection to the PostgreSQL server and authenticates, throwing on failure.- Allows callers to verify connectivity before issuing queries or claiming "connected" in UI.
- Implements the
IVectorStore.VerifyConnectionAsynccontract introduced in Abstractions v2.2.0.
TextSearchModeโ configurable text search strategy for hybrid search (TsVector|Trigram).TsVector(default): PostgreSQLtsvector / tsqueryfull-text search. Works well for European languages.Trigram:pg_trgmword_similaritymatching. Better for CJK languages (Korean, Japanese, Chinese) and agglutinative languages where PostgreSQL lacks built-in morphological analysis.
TextSearchConfigโ configurable PostgreSQL text search configuration (default:"simple"). Only used inTsVectormode.- Trigram index auto-provisioning โ when
TextSearchMode = TrigramandEnsureSchema = true, automatically createspg_trgmextension and GIN trigram index (gin_trgm_ops) on thecontentcolumn. - Hybrid search
text_candidatesCTE is now generated byBuildTextCandidatesCte, supporting bothTsVectorandTrigrammodes.
Changed
- TsVector mode: OR-based
to_tsqueryโ replacedplainto_tsquery(AND logic) withto_tsqueryusing OR (|) token joining.plainto_tsquery('simple', 'OPM ์ด๋ฒคํธ ์ฝ๋')โ'opm' & '์ด๋ฒคํธ' & '์ฝ๋'(AND โ too restrictive, requires all terms to match)- New approach โ
'opm' | '์ด๋ฒคํธ' | '์ฝ๋'(OR โ standard BM25 behavior; documents matching more terms still rank higher viats_rank)
- Script boundary normalization (
NormalizeScriptBoundaries) โ new internal helper that inserts spaces at script boundaries (LatinโHangul, LatinโCJK, HiraganaโKatakana, etc.) so PostgreSQL'sto_tsvectortokenises mixed-script words correctly.- e.g.
"eventํ ์ด๋ธ์"โ"event ํ ์ด๋ธ์","ใใผใฟํ ์ด๋ธ"โ"ใใผใฟ ํ ์ด๋ธ" - Applied during upsert (
content_tsvis computed from the normalised text) and schema migration (EnsureSchemaAsyncbackfills existing rows withregexp_replace).
- e.g.
Compatibility
- Fully backward compatible with v10.2.x. Default
TextSearchMode.TsVectorpreserves existing behavior. - Existing
content_tsvdata will be re-normalised whenEnsureSchemaAsyncruns on upgrade.
v10.2.0
Added
PostgresStoresupports native hybrid search viaIVectorStore.HybridSearchAsync.HybridSearchAsyncruns parallel queries โ PostgreSQL full-text search andpgvectorsimilarity search โ then merges results via Reciprocal Rank Fusion (RRF) withk=60.- Uses
ts_rankfor keyword scoring and distance-strategy-aware similarity scoring. - Supports all existing filters: namespace, scope, metadata, and min-score.
- Persisted
content_tsvcolumn for full-text search โ hybrid search now reads from the pre-computedcontent_tsv(tsvector) column instead of recalculatingto_tsvector(content)on every query.contentremains nullable to support deployments that prohibit original text storage;content_tsvis required for lexical retrieval.- Recommended GIN index:
CREATE INDEX idx_vectors_fts ON public.vectors USING gin (content_tsv);
Breaking Changes โ Schema
- New required column
content_tsv tsvectoradded to thevectorstable. - Existing tables must be migrated before upgrading (see migration SQL below).
Compatibility
- Breaking schema change from v10.1.0 โ the
content_tsvcolumn must exist before using hybrid search. - Existing
SearchAsyncbehavior unchanged.HybridSearchAsyncis only invoked whenUseHybridSearch()is configured in the RAG pipeline.
v10.1.0
Breaking Changes โ Namespace Now Optional
Aligned with IVectorStore v2.0.0: namespace moved from method parameter to VectorRecord.Namespace / VectorFilter.Namespace properties.
- All methods no longer take
string @namespaceas a parameter. - Namespace is read from
record.Namespaceorfilter.Namespace(defaults to"default"when null). NamespaceExistsAsync/CreateNamespaceAsync/DeleteNamespaceAsyncremoved โ useDeleteByFilterAsync(new VectorFilter { Namespace = "ns" }).GetAsync/DeleteAsyncnow accept optionalVectorFilter? filterfor namespace/scope narrowing.PostgresVectorStoreโPostgresStore: Class renamed for shorter DX.PostgresVectorStoreOptionsโPostgresOptions: Options class renamed.
Breaking Changes โ Schema
- Primary key remains
(namespace, id). - Column
collectionโnamespace, columnnamespaceโscope(from v10.0.0 terminology).
Migration from v10.0.0
For existing PostgreSQL databases, run the following migration before upgrading:
-- 1. Rename columns (order matters: rename 'namespace' first to avoid conflict)
ALTER TABLE "public"."vectors" RENAME COLUMN namespace TO scope;
ALTER TABLE "public"."vectors" RENAME COLUMN collection TO namespace;
-- 2. Recreate composite index
DROP INDEX IF EXISTS idx_vectors_collection_ns;
CREATE INDEX idx_vectors_ns_scope ON "public"."vectors" (namespace, scope);
-- 3. Recreate primary key
ALTER TABLE "public"."vectors" DROP CONSTRAINT vectors_pkey;
ALTER TABLE "public"."vectors" ADD PRIMARY KEY (namespace, id);
Fluent Builder API
var store = new PostgresStore(options);
await store.InNamespace("docs").InScope("tenant-1").UpsertAsync(record);
var results = await store.InNamespace("docs").InScope("tenant-1").SearchAsync(queryVector);
v10.0.0
Initial Release
PostgresVectorStoreโ pgvector-based implementation ofIVectorStore.- Similarity search with
DistanceStrategysupport:Cosine,Euclidean,InnerProduct. - Single-table design with
collectioncolumn for logical isolation. - Upsert with
ON CONFLICT ... DO UPDATE(single and batch viaNpgsqlBatch). - Metadata filtering via jsonb containment (
@>). - Namespace isolation filter.
- Minimum score threshold filter.
EnsureSchemaoption for automatic table/extension/index provisioning.- Schema/table name validation to prevent SQL injection.
- Vector index support via typed settings:
HnswIndexOptions(M,EfConstruction,EfSearch)IvfFlatIndexOptions(Lists,Probes)NoIndexOptions
- Per-request runtime tuning via algorithm-specific options:
HnswSearchRuntimeOptionsIvfFlatSearchRuntimeOptionsSearchProfilepresets (Fast,Balanced,HighRecall)
FailFastOnIndexCreationFailureoption for index provisioning behavior.gin(metadata)and(collection, namespace)indexes.
Fixed
SearchAsync: RefactoredNpgsqlCommand/NpgsqlDataReaderto block-scopedusingto ensure disposal beforetx.CommitAsync(), preventing Npgsql "A command is already in progress" errors.ApplySearchRuntimeSettingsAsync: Each index branch now creates its own block-scopedNpgsqlCommand, preventing shared-command conflicts.SET LOCALstatements changed from parameterized queries to string interpolation โ PostgreSQLSET LOCALdoes not support$1-style parameters.