Repository navigation
Keep unsupplied fields indexed after a merge - #99
Open
danielgreen wants to merge 2 commits into
Open
danielgreen wants to merge 2 commits into
danielgreen wants to merge 2 commits into
Conversation
ConvertSearchDoc turned each field's stored Lucene fields back into JSON inline. That code moves, unchanged, into SearchFieldExtensions.GetStoredValue, which returns the raw stored value. ConvertSearchDoc still applies retrievable, $select and the non-retrievable sub-fields of a complex value, as before. No change in behaviour. The switch's Edm.ComplexType case goes: it was unreachable, since complex fields return earlier. This lets the merge action read a stored document back with the same code.
After a merge or mergeOrUpload on a document that already existed, the document kept its values but stopped matching filters, facets and vector queries on the fields the merge did not supply. For example, after merging only Title, "Id eq '1' and Source eq 'blob-1'" no longer found the document. The cause: the merge wrote back the stored fields returned by IndexSearcher.Doc, which carry no indexed terms or doc values. A merge now reads the stored document back as JSON with GetStoredValue, applies the item's fields on top, and indexes the result as an upload does. An explicit null still clears a field, because null values are not indexed. This replaces the earlier partial repairs, which the new merge covers: ClearedFields, GetClearedFields and GetLuceneFieldNames (feature23#71: remove every Lucene copy of a field set to null) and RestoreVectorDocValues (feature23#46: rebuild a vector's packed copy). It also keeps the facet, geo and complex-element doc values that RestoreVectorDocValues' comment noted were still lost. Limit: a field that is not retrievable has no stored copy (except a vector), so a merge that does not supply it loses its value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #102
What was wrong
After a
mergeormergeOrUploadon a document that already existed, the document kept its values but stopped matching filters, facets and vector queries on the fields the merge did not send. Only its key still matched.For example, upload a document, then merge only
Title:Id eq '1'finds it.Id eq '1' and Source eq 'blob-1'does not.The merge read the old document with
IndexSearcher.Doc, which returns stored fields only, and wrote those back. Stored fields carry no indexed terms or doc values.What changed
Two commits, so each can be checked on its own:
GetStoredValue. The code inLuceneNetIndexSearcher.ConvertSearchDocthat turns each field's stored Lucene fields back into JSON moves, unchanged, intoSearchFieldExtensions.GetStoredValue.ConvertSearchDocstill appliesretrievable,$selectand the hidden sub-fields of a complex value. No change in behaviour: all existing tests pass on this commit alone. The switch'sEdm.ComplexTypecase goes, as it was unreachable.GetStoredValue, puts the item's fields over it, and indexes the result the same way an upload does.GetStoredValuedoes not checkretrievable, so a merge keeps a vector that is not retrievable.Limit: a field marked
retrievable: falsehas no stored copy (except a vector), so a merge that does not send it loses its value. The same happens before this change.Why the removed code is no longer needed
Most of the lines removed from
UpsertIndexDocumentActionBase.csare comments. The code removed was a set of repairs, each for one symptom of the bug above. Indexing the whole document again makes each one unnecessary:ClearedFields,GetClearedFieldsMergeNullClearsFieldTests,MergeNullClearsFieldIntegrationTestsGetLuceneFieldNamesRestoreVectorDocValuesVectorFieldTests.Merge_OfAnotherField_KeepsTheVector,VectorSearchTests.MergedDocument_IsStillFoundByVectorSearchMergeDocumentoverloadRestoreVectorDocValuesalready noted the remaining gap: "The same reconstruction drops facet, geo and complex-element doc values too, which is a pre-existing fault worth fixing on its own terms rather than quietly here." This change fixes those too; the new tests check facets, geography points and complex fields after a merge.The lines removed from
LuceneNetIndexSearcher.csare the ones moved intoGetStoredValuein the first commit.Cost: a merge now analyses the document's text and parses its vectors again, where it used to copy stored fields. A merge of a large document is slower; it does not change the result.
Tests
MergeKeepsFieldsIndexedTests(new, 20 tests): after a merge of one field, filters on each other field type (string, string collection, Int32, Boolean, date, geography point, complex field, complex collection), a text search, a facet, replacement of the merged field, and two merges in a row. 18 of the 20 fail without the change.dotnet testfrom the repo root currently stops before any test runs, onmaintoo: restoringAzureSearchEmulator.Aspirefails with NU1902, a moderate advisory for MessagePack 2.5.302 (GHSA-qhrr-8q5h-9q3h) that the project treats as an error. I ran the unit and integration test projects directly.