Skip to content

fix pgvector metadata filtering (parser + wire-up) - #293

Open
Goodnight77 wants to merge 5 commits into
qdrant:masterfrom
Goodnight77:fix/pgvector-parser-equality
Open

Goodnight77 wants to merge 5 commits into
qdrant:masterfrom
Goodnight77:fix/pgvector-parser-equality

Conversation

@Goodnight77

@Goodnight77 Goodnight77 commented Apr 30, 2026

Copy link
Copy Markdown

description

Fix exact-match filter in pgvector parser and wire up filtered search

Previous version used json.dumps(value) for the filter value, which quotes strings with ", and Postgres reads double quotes as an identifier, not a string literal, so filtered queries still failed. Also, the parser was never called from search_one, so none of this ran

This PR:

  • binds filter values as psycopg params (Jsonb(value)) instead of string-embedding them
  • adds a payload column, stores record.metadata in it on upload
  • calls the parser from search_one and applies the resulting WHERE clause

Tested against a real pgvector/pgvector:pg16 container exact-match and range filters return correct rows

@tellet-q
tellet-q self-requested a review June 11, 2026 09:37

@tellet-q tellet-q left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Right now this code is a dead one, nothing executes it. So, the change is only required for possible future use. Apart from that it requires extension, alone it won't parse. json.dumps(value) renders a string as "Shoes", and double quotes in Postgres mean a quoted identifier, so you'd still get ERROR.

@Goodnight77

Copy link
Copy Markdown
Author

@tellet-q
fixed both issues you raised:

  • values now go through psycopg params instead of being string-embedded, no more double-quote/identifier bug
  • wired it up for real: added a payload column, upload stores metadata in it, search now applies the filter

Tested against a real pgvector container, filters return correct results

@Goodnight77 Goodnight77 changed the title fix pgvector parser to use sql equality operator fix pgvector metadata filtering (parser + wire-up) Aug 19, 2026
@Goodnight77
Goodnight77 requested a review from tellet-q September 2, 2026 23:23

@tellet-q tellet-q left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo is mostly focused on benchmarking Qdrant, so pgvector engine is not the main line here. I still have a couple of notes for the change:

  • Please move the tests from main to smth like tests/engine/clients/pgvector/test_pgvector_parser.py
  • list-valued fields match nothing. payload -> 'labels' = '"lab_0"'::jsonb is false when labels is an array. It is an array in arxiv-titles-384-angular-filters. Qdrant (MatchValue) and Elasticsearch treat match-against-array as "contains", so pgvector would report precision 0 where every other engine scores normally.
  • Unsupported filter types now abort the whole run. Before this PR search_one never called the parser, so nothing could raise, not applicable for most of the datasets, but still worth mentioning.
  • Is GIN index really needed here?

@Goodnight77

Copy link
Copy Markdown
Author

Thanks, @tellet-q all four addressed:

  • tests moved to tests/engine/clients/pgvector/test_pgvector_parser.py
  • exact match now uses @> instead of =: equality on scalars, "contains" on arrays, same as Qdrant/ES. Verified on PG 16, labels rows match
  • geo datasets raise IncompatibilityError in configure, so they're skipped before upload
  • GIN removed. It can't serve payload -> key expressions (checked with EXPLAIN), so it was dead weight

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants