Skip to content

Fix $filter on searchable string fields (#27)#29

Merged
paulirwin merged 1 commit into
mainfrom
fix-filter-on-searchable-string-field
Apr 23, 2026
Merged

Fix $filter on searchable string fields (#27)#29
paulirwin merged 1 commit into
mainfrom
fix-filter-on-searchable-string-field

Conversation

@paulirwin
Copy link
Copy Markdown
Member

Fixes #27.

Problem

When an Edm.String field was Searchable=true (the default) and also Filterable=true, $filter queries like Category eq 'Electronics' returned zero results. The field was indexed only as a Lucene TextField, so the StandardAnalyzer lowercased and tokenized the value at index time ("Electronics""electronics"), but the filter path built an exact TermQuery from the raw literal and never matched. The reporter's workaround — setting IsSearchable=false — worked only because it collapsed the field into the StringField branch.

Per Filters in Azure AI Search and Analyzers for text processing: filters run on raw, non-analyzed content, independent of whether the field is searchable.

Fix

  • SearchFieldExtensions.CreateFieldCreateFields (now returns IEnumerable<IIndexableField>). For Edm.String fields that are searchable and filterable/sortable/facetable, index both a TextField (analyzed, for $search) and a StringField (raw, for $filter/$orderby/facets) under the same field name. Lucene merges postings by field name, so TermQuery matches the raw side while analyzed-token search still works.
  • UpsertIndexDocumentActionBase.MergeDocument: remove existing fields once per distinct name before re-adding, so dual-indexed fields aren't dropped during upsert.
  • ODataQueryVisitor: added EnsureFilterable(path) at the filter entry points — a filter referencing a field with Filterable=false now throws, matching Azure's behavior.

Test plan

🤖 Generated with Claude Code

Searchable Edm.String fields were indexed only as analyzed TextFields,
so an exact TermQuery built from the filter literal never matched the
lowercased, tokenized terms. Filterable/sortable/facetable searchable
string fields now also emit a non-analyzed StringField under the same
name, matching Azure's semantics where filters run on raw, non-analyzed
content (https://learn.microsoft.com/azure/search/search-analyzers).

Also: reject filters against fields with Filterable=false, and fix
MergeDocument so dual-indexed fields aren't accidentally dropped
during upsert.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@paulirwin paulirwin merged commit 825d11a into main Apr 23, 2026
2 of 3 checks passed
@paulirwin paulirwin deleted the fix-filter-on-searchable-string-field branch April 23, 2026 17:54
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.

Searchable and Filterable fields return no results with filters applied

1 participant