Skip to content

perf: vector.neighbors 'where' predicate so a property restriction does not build the set of every RID in scopeĀ #10169

Closed

Description

@robfrank

Follow-up of #10129 (proposed change 4, marked optional there).

The idiomatic way to restrict vector.neighbors by a property is a filter subquery that returns every RID in scope:

`vector.neighbors`('Passage[embedding]', :embedding, :fetch,
  { filter: (SELECT @rid FROM Passage WHERE embed_space = :space).@rid })

That loads every record in scope and builds a HashSet<RID> on each call: 3-5 ms on 11k rows in the #10129 measurement, even when the filter keeps everything.

Proposal: accept a property predicate applied to candidates during the search, e.g. where: { embed_space: :space } (equality map) or a SQL condition string, evaluated on each candidate record the search already loads, so restricting by a property no longer means materializing the set of every RID in scope. Same option for vector.sparseNeighbors.

Out of scope for #10129, which fixed the record loads and per-row copies in vector.fuse / vector.rerank; this is a new option on the search API (parser, OpenAPI, docs).

Activity

  1. added this to the 26.11.1 milestone on Oct 16, 2026
  2. added
    in progressThe team is actively working on this issue
    on Oct 16, 2026
  3. self-assigned this
    on Oct 16, 2026
  4. added a commit that references this issue on Oct 17, 2026
  5. lvca commented on Oct 17, 2026

    @lvca
    Member

    Added in #10185 (26.11.1): vector.neighbors and vector.sparseNeighbors take a where option. It is tested only on the candidates the search visits, so nothing is built up front for the whole type:

    SELECT expand(`vector.neighbors`('Passage[embedding]', :q, 10, { where: { space: :space } }))
    SELECT expand(`vector.neighbors`('Passage[embedding]', :q, 10, { where: 'space = :space AND year >= :minYear' }))

    It takes a map of property to value, or a SQL condition with named parameters (? is refused), and it can be combined with filter. A very selective predicate may end up testing every record to return k results; for a small, known set of RIDs, filter is still the cheaper choice.


    ā¤ļø Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.

  6. removed
    in progressThe team is actively working on this issue
    on Oct 17, 2026
  7. added a commit that references this issue on Oct 17, 2026
  8. added a commit that references this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestperformanceseverity:minorCosmetic, documentation, edge case, or a workaround existsvectorVector index and embedding search

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions