Skip to content

feat(base-query): Indexable(each = true) with contains/doesNotContain#88

Merged
deer merged 1 commit into
mainfrom
multi_valued_index
Jun 16, 2026
Merged

feat(base-query): Indexable(each = true) with contains/doesNotContain#88
deer merged 1 commit into
mainfrom
multi_valued_index

Conversation

@deer

@deer deer commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator
  • @Indexable gains an each() attribute (default false). When each = true, the function is expected to return a Stream, Collection, or Iterable, and each element is indexed individually as a separate reverse-map key. When each = false (the default), the return value is treated as a single scalar key, exactly as before. Intent is declared at the field rather than inferred at runtime from the return type, so a function returning List<Tag> is never silently treated as multi-valued unless the author explicitly opts in.
  • AbstractHeapBasedIndex routes scalar and each functions through entirely separate code paths (indexNonUnique/indexEach, reindexNonUnique/reindexEach) backed by two new memoizers. The previous putNonUniqueValue with its runtime instanceof dispatch is removed. If an each = true function returns a non-container value, it throws at index time with a clear message.
  • Condition gains contains(Object element) for O(1) indexed membership lookup (falling back to a linear scan for non-indexed functions) and doesNotContain(Object element) which always scans. A matches-based default was considered for doesNotContain and rejected: Matches.findAll() iterates over individual reverse-map keys rather than the original container, which would return wrong results for indexed each-functions.
  • shouldDistinguishScalarIndexingFromEachIndexing puts both modes side by side on the same List<Color> field -- COLORS_SCALAR with isEqualTo(list) and COLORS_EACH with contains(element) — making the difference concrete and executable. Additional contract tests cover Collection and Iterable element types, reindex after mutation, the non-indexed fallback path, and doesNotContain exclusion semantics.

@deer deer merged commit 3d0ff88 into main Jun 16, 2026
3 checks passed
@deer deer deleted the multi_valued_index branch June 16, 2026 19:39
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.

1 participant