Move merge compatibility logic from MappedFieldType to FieldMapper#56915
Move merge compatibility logic from MappedFieldType to FieldMapper#56915romseygeek merged 18 commits intoelastic:masterfrom
Conversation
|
Pinging @elastic/es-search (:Search/Mapping) |
jtibshirani
left a comment
There was a problem hiding this comment.
It's great you're cleaning up FieldMapper! I'm excited about the plan in #56814.
I was wondering if we could simplify the method structure more by combining the compatibility checks and merging together. This seems natural to me -- for each option you validate if it can be changed, and then apply the change if possible. Subclasses would only need to override a single method.
A new call structure would look something like this:
FieldMapper#merge
-> FieldMapper#mergeSharedOptions (handles both compatibility checks and updates field type, copy to, etc.)
-> FieldMapper#mergeOptions (overridden by subclasses to perform both compatibility checks and updates options)
This could be done as a follow-up refactor if we wanted to keep the current PR simple, as a straight reshuffling of methods.
|
|
||
| protected abstract T newBuilder(); | ||
|
|
||
| private static class BogusFieldType extends MappedFieldType { |
There was a problem hiding this comment.
It seems like we could reuse the existing test classes MockFieldMapper and FakeFieldType here.
| } | ||
| } | ||
|
|
||
| public void testFreeze() { |
There was a problem hiding this comment.
It looks like this test was lost in the refactor. Do we have plans to replace it or make it no longer necessary?
There was a problem hiding this comment.
The next step will be to decouple FieldType and MappedFieldType entirely, so there won't need to be a freeze() method here at all.
I like this a lot, it would make things a lot clearer. Let's do it in a follow-up to keep this PR reasonably contained? |
jtibshirani
left a comment
There was a problem hiding this comment.
I left a last round of comments.
Let's do it in a follow-up to keep this PR reasonably contained?
Sounds good to me.
| } | ||
| IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> | ||
| mapperService.merge("type", new CompressedXContent(Strings.toString(update)), MapperService.MergeReason.MAPPING_UPDATE)); | ||
| assertThat(e.getMessage(), containsString("mapper [foo] of different type, current_type [long], merged_type [double]")); |
There was a problem hiding this comment.
To me the error message "mapper [foo] cannot be changed from type [long] to [double]" is a lot clearer, we could prefer that original wording.
On a related note, it looks like MappedFieldType#checkTypeName is now unused and can be removed.
| ft1 = createNamedDefaultFieldType(); | ||
| ft2 = createNamedDefaultFieldType(); | ||
| modifier.modify(ft2); | ||
| assertFieldTypeNotEquals(modifier.property, ft1, ft2); |
There was a problem hiding this comment.
I just noticed we've lost test coverage for the equals method, which is used in FieldTypeLookup. This is too bad, I wonder if we could we keep these modifiers around or switch to using EqualsHashCodeTestUtils#checkEqualsAndHashCode.
There was a problem hiding this comment.
With luck we'll be able to simplify a lot of the MapperService lookup stuff once things have been rearranged, but for now I agree we still need these tests. I've modified FieldTypeTestCase to allow testing of subtypes with modifiers, using EqualsHashCodeTestUtils.
| FieldMapper mapper = (FieldMapper) newBuilder().build(context); | ||
| FieldMapper toMerge = new FieldMapper("bogus", new BogusFieldType(), new BogusFieldType(), | ||
| SETTINGS, FieldMapper.MultiFields.empty(), FieldMapper.CopyTo.empty()) { | ||
| FieldMapper toMerge = new FieldMapper("bogus", new MockFieldMapper.FakeFieldType(), |
There was a problem hiding this comment.
I think this could just be FIeldMapper toMerge = new MockFieldMapper("bogus") ?
There was a problem hiding this comment.
It could, thanks!
This turned out to make the final patch slightly smaller and easier to review, so I added it in. Thanks for the suggestion @jtibshirani ! |
jtibshirani
left a comment
There was a problem hiding this comment.
I left some comments about field type tests that were deleted. I think they need to be restored, but once that's done it looks ready to merge.
| import org.elasticsearch.index.mapper.MappedFieldType; | ||
| import org.junit.Before; | ||
|
|
||
| public class GeoShapeWithDocValuesFieldTypeTests extends FieldTypeTestCase { |
There was a problem hiding this comment.
Should this test have been deleted?
There was a problem hiding this comment.
It should not! Have restored it.
| /** | ||
| * Merge type-specific options and check for incompatible settings in mappings to be merged | ||
| */ | ||
| protected abstract void mergeOptions(FieldMapper other, List<String> conflicts); |
There was a problem hiding this comment.
Great that this is abstract, I like how it encourages implementors to think through what can be updated vs. not.
| throw new IllegalArgumentException("mapper [" + fieldType.name() + "] cannot be changed from type [" | ||
| + contentType() + "] to [" + mergeWith.getClass().getSimpleName() + "]"); | ||
| } | ||
| merged.mergeSharedOptions((FieldMapper)mergeWith, conflicts); |
There was a problem hiding this comment.
Small comment, calling mergeOptions directly from here could be nice:
FieldMapper fieldMapper = (FieldMapper) mergeWith;
merged.mergeSharedOptions(fieldMapper, conflicts);
merged.mergeOptions(fieldMapper, conflicts);
There was a problem hiding this comment.
++, I've rearranged things here.
| } | ||
|
|
||
| @Before | ||
| public void setupProperties() { |
There was a problem hiding this comment.
I think we dropped this modifier accidentally.
There was a problem hiding this comment.
scaling_factor can't be updated, so we'd never be in a position when FieldTypeLookup would be comparing and old and new types with different scaling factors.
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public class CompletionFieldTypeTests extends FieldTypeTestCase { |
There was a problem hiding this comment.
Should this have been deleted?
There was a problem hiding this comment.
Again, none of these values can be updated in a merge, so we don't need an equality check.
…56915) Merging logic is currently split between FieldMapper, with its merge() method, and MappedFieldType, which checks for merging compatibility. The compatibility checks are called from a third class, MappingMergeValidator. This makes it difficult to reason about what is or is not compatible in updates, and even what is in fact updateable - we have a number of tests that check compatibility on changes in mapping configuration that are not in fact possible. This commit refactors the compatibility logic so that it all sits on FieldMapper, and makes it called at merge time. It adds a new FieldMapperTestCase base class that FieldMapper tests can extend, and moves the compatibility testing machinery from FieldTypeTestCase to here. Relates to #56814
I think this is a left-over from #56915 where a change in assertion message didn't make it to this very rare-case assertion.
Merging logic is currently split between FieldMapper, with its
merge()method, andMappedFieldType, which checks for merging compatibility. The compatibility checks
are called from a third class,
MappingMergeValidator. This makes it difficult to reasonabout what is or is not compatible in updates, and even what is in fact updateable - we
have a number of tests that check compatibility on changes in mapping configuration
that are not in fact possible.
This commit refactors the compatibility logic so that it all sits on FieldMapper, and
makes it called at merge time. It adds a new
FieldMapperTestCasebase class thatFieldMappertests can extend, and moves the compatibility testing machinery fromFieldTypeTestCaseto here.Relates to #56814