Skip to content

Commit 563b273

Browse files
authored
Annotated text type should extend TextFieldType (#49555)
The annotated text mapper has a field type that currently extends StringFieldType, which means that all the positional-related query factory methods need to be copied over from TextFieldType. In addition, MappedFieldType.intervals() hasn't been overridden, so you can't use intervals queries with annotated text - a major drawback, since one of the purposes of annotated text is to be able to run positional queries against annotations. This commit changes the annotated text field type to extend TextFieldType instead, adding tests to ensure that position queries work correctly. Closes #49289
1 parent 63b944c commit 563b273

File tree

5 files changed

+83
-47
lines changed

5 files changed

+83
-47
lines changed

plugins/mapper-annotated-text/src/main/java/org/elasticsearch/index/mapper/annotatedtext/AnnotatedTextFieldMapper.java

+1-42
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,19 @@
3131
import org.apache.lucene.document.Field;
3232
import org.apache.lucene.index.IndexOptions;
3333
import org.apache.lucene.index.IndexableField;
34-
import org.apache.lucene.index.Term;
35-
import org.apache.lucene.search.NormsFieldExistsQuery;
36-
import org.apache.lucene.search.PrefixQuery;
37-
import org.apache.lucene.search.Query;
38-
import org.apache.lucene.search.TermQuery;
39-
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
40-
import org.apache.lucene.search.spans.SpanQuery;
4134
import org.elasticsearch.ElasticsearchParseException;
4235
import org.elasticsearch.common.settings.Settings;
4336
import org.elasticsearch.common.xcontent.XContentBuilder;
4437
import org.elasticsearch.common.xcontent.support.XContentMapValues;
4538
import org.elasticsearch.index.analysis.AnalyzerScope;
4639
import org.elasticsearch.index.analysis.NamedAnalyzer;
4740
import org.elasticsearch.index.mapper.FieldMapper;
48-
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
4941
import org.elasticsearch.index.mapper.MappedFieldType;
5042
import org.elasticsearch.index.mapper.Mapper;
5143
import org.elasticsearch.index.mapper.MapperParsingException;
5244
import org.elasticsearch.index.mapper.ParseContext;
53-
import org.elasticsearch.index.mapper.StringFieldType;
5445
import org.elasticsearch.index.mapper.TextFieldMapper;
5546
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText.AnnotationToken;
56-
import org.elasticsearch.index.query.QueryShardContext;
5747
import org.elasticsearch.search.fetch.FetchSubPhase.HitContext;
5848

5949
import java.io.IOException;
@@ -531,7 +521,7 @@ private void emitAnnotation(int firstSpannedTextPosInc, int annotationPosLen) th
531521
}
532522

533523

534-
public static final class AnnotatedTextFieldType extends StringFieldType {
524+
public static final class AnnotatedTextFieldType extends TextFieldMapper.TextFieldType {
535525

536526
public AnnotatedTextFieldType() {
537527
setTokenized(true);
@@ -562,37 +552,6 @@ public String typeName() {
562552
return CONTENT_TYPE;
563553
}
564554

565-
@Override
566-
public Query existsQuery(QueryShardContext context) {
567-
if (omitNorms()) {
568-
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
569-
} else {
570-
return new NormsFieldExistsQuery(name());
571-
}
572-
}
573-
574-
@Override
575-
public SpanQuery spanPrefixQuery(String value, SpanMultiTermQueryWrapper.SpanRewriteMethod method, QueryShardContext context) {
576-
SpanMultiTermQueryWrapper<?> spanMulti =
577-
new SpanMultiTermQueryWrapper<>(new PrefixQuery(new Term(name(), indexedValueForSearch(value))));
578-
spanMulti.setRewriteMethod(method);
579-
return spanMulti;
580-
}
581-
582-
@Override
583-
public Query phraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) throws IOException {
584-
return TextFieldMapper.createPhraseQuery(stream, name(), slop, enablePositionIncrements);
585-
}
586-
587-
@Override
588-
public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) throws IOException {
589-
return TextFieldMapper.createPhraseQuery(stream, name(), slop, enablePositionIncrements);
590-
}
591-
592-
@Override
593-
public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions) throws IOException {
594-
return TextFieldMapper.createPhrasePrefixQuery(stream, name(), slop, maxExpansions, null, null);
595-
}
596555
}
597556

598557
private int positionIncrementGap;

plugins/mapper-annotated-text/src/test/java/org/elasticsearch/index/mapper/annotatedtext/AnnotatedTextFieldMapperTests.java

-2
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,4 @@ public void testEmptyName() throws IOException {
672672
assertThat(e.getMessage(), containsString("name cannot be empty string"));
673673
}
674674

675-
676-
677675
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.index.mapper.annotatedtext;
21+
22+
import org.apache.lucene.analysis.standard.StandardAnalyzer;
23+
import org.apache.lucene.queries.intervals.Intervals;
24+
import org.apache.lucene.queries.intervals.IntervalsSource;
25+
import org.elasticsearch.index.analysis.AnalyzerScope;
26+
import org.elasticsearch.index.analysis.NamedAnalyzer;
27+
import org.elasticsearch.index.mapper.FieldTypeTestCase;
28+
import org.elasticsearch.index.mapper.MappedFieldType;
29+
30+
import java.io.IOException;
31+
32+
public class AnnotatedTextFieldTypeTests extends FieldTypeTestCase {
33+
@Override
34+
protected MappedFieldType createDefaultFieldType() {
35+
return new AnnotatedTextFieldMapper.AnnotatedTextFieldType();
36+
}
37+
38+
public void testIntervals() throws IOException {
39+
MappedFieldType ft = createDefaultFieldType();
40+
NamedAnalyzer a = new NamedAnalyzer("name", AnalyzerScope.INDEX, new StandardAnalyzer());
41+
IntervalsSource source = ft.intervals("Donald Trump", 0, true, a, false);
42+
assertEquals(Intervals.phrase(Intervals.term("donald"), Intervals.term("trump")), source);
43+
}
44+
}

plugins/mapper-annotated-text/src/test/resources/rest-api-spec/test/mapper_annotatedtext/10_basic.yml

+37-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,41 @@
3939

4040
- match: {hits.hits.0.highlight.text.0: "The [quick](_hit_term=quick) brown fox is brown."}
4141

42+
- do:
43+
search:
44+
body:
45+
query:
46+
intervals:
47+
text:
48+
match:
49+
query: entity_3789 brown
50+
51+
- match: { hits.total.value: 1 }
52+
53+
- do:
54+
search:
55+
body:
56+
query:
57+
span_near:
58+
clauses: [
59+
span_term: { text: entity_3789 },
60+
span_term: { text: brown }
61+
]
62+
in_order: true
63+
slop: 10
64+
65+
- match: { hits.total.value: 1 }
66+
67+
- do:
68+
search:
69+
body:
70+
query:
71+
match_phrase:
72+
text: "fox is brown"
73+
74+
- match: { hits.total.value: 1 }
75+
76+
4277
---
4378
"issue 39395 thread safety issue -requires multiple calls to reveal":
4479
- do:
@@ -57,13 +92,13 @@
5792
index:
5893
index: annotated
5994
id: 1
60-
body:
95+
body:
6196
"my_field" : "[A](~MARK0&~MARK0) [B](~MARK1)"
6297
- do:
6398
index:
6499
index: annotated
65100
id: 2
66-
body:
101+
body:
67102
"my_field" : "[A](~MARK0) [C](~MARK2)"
68103
refresh: true
69104
- do:

server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ public String toString() {
511511
}
512512
}
513513

514-
public static final class TextFieldType extends StringFieldType {
514+
public static class TextFieldType extends StringFieldType {
515515

516516
private boolean fielddata;
517517
private double fielddataMinFrequency;

0 commit comments

Comments
 (0)