mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 17:34:17 -04:00
Add source fallback support for match_only_text mapped type (#89473)
This change adds access to mapped match_only_text fields via the Painless scripting fields API. The values returned from a match_only_text field via the scripting fields API always use source as described by (#81246). These are not available via doc values so there are no bwc issues.
This commit is contained in:
parent
b15f6dd6d0
commit
58fafe224f
4 changed files with 170 additions and 1 deletions
5
docs/changelog/89473.yaml
Normal file
5
docs/changelog/89473.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pr: 89473
|
||||||
|
summary: Add source fallback support for `match_only_text` mapped type
|
||||||
|
area: Mapping
|
||||||
|
type: enhancement
|
||||||
|
issues: []
|
|
@ -81,6 +81,8 @@ setup:
|
||||||
fielddata: true
|
fielddata: true
|
||||||
text_no_field_data:
|
text_no_field_data:
|
||||||
type: text
|
type: text
|
||||||
|
match_only_text:
|
||||||
|
type: match_only_text
|
||||||
token_count:
|
token_count:
|
||||||
type: token_count
|
type: token_count
|
||||||
analyzer: standard
|
analyzer: standard
|
||||||
|
@ -125,6 +127,7 @@ setup:
|
||||||
scaled_float_no_doc_values: 3.14
|
scaled_float_no_doc_values: 3.14
|
||||||
text: "Lots of text."
|
text: "Lots of text."
|
||||||
text_no_field_data: "Lots of text."
|
text_no_field_data: "Lots of text."
|
||||||
|
match_only_text: "Lots of text."
|
||||||
token_count: count all these words please
|
token_count: count all these words please
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
|
@ -169,7 +172,7 @@ setup:
|
||||||
scaled_float_no_doc_values: [2.5, -3.5]
|
scaled_float_no_doc_values: [2.5, -3.5]
|
||||||
text: ["Lots of text.", "even more text", "SOOOOO much text"]
|
text: ["Lots of text.", "even more text", "SOOOOO much text"]
|
||||||
text_no_field_data: ["Lots of text.", "even more text", "SOOOOO much text"]
|
text_no_field_data: ["Lots of text.", "even more text", "SOOOOO much text"]
|
||||||
|
match_only_text: ["Lots of text.", "even more text", "SOOOOO much text"]
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
indices.refresh: {}
|
indices.refresh: {}
|
||||||
|
@ -3234,6 +3237,136 @@ setup:
|
||||||
- match: { hits.hits.1.fields.field.0: "0" }
|
- match: { hits.hits.1.fields.field.0: "0" }
|
||||||
- match: { hits.hits.2.fields.field.0: "Lots of text.SOOOOO much texteven more text3" }
|
- match: { hits.hits.2.fields.field.0: "Lots of text.SOOOOO much texteven more text3" }
|
||||||
|
|
||||||
|
---
|
||||||
|
"match_only_text":
|
||||||
|
- do:
|
||||||
|
catch: bad_request
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
query: { term: { _id: "1" } }
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "doc['match_only_text'].get(0)"
|
||||||
|
- match: { error.failed_shards.0.reason.caused_by.type: "illegal_argument_exception" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: bad_request
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
query: { term: { _id: "1" } }
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "doc['match_only_text'].value"
|
||||||
|
- match: { error.failed_shards.0.reason.caused_by.type: "illegal_argument_exception" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "field('match_only_text').get('')"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "Lots of text." }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "Lots of text." }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "/* avoid yaml stash */ $('match_only_text', '')"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "Lots of text." }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "Lots of text." }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "String defaultText = 'default text'; field('match_only_text').get(defaultText)"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "Lots of text." }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "default text" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "Lots of text." }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "String defaultText = 'default text'; $('match_only_text', defaultText)"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "Lots of text." }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "default text" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "Lots of text." }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "field('match_only_text').get(1, '')"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "SOOOOO much text" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "String defaultText = 'default text'; field('match_only_text').get(1, defaultText)"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "default text" }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "default text" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "SOOOOO much text" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "field('match_only_text').get(1, '')"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "SOOOOO much text" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
rest_total_hits_as_int: true
|
||||||
|
body:
|
||||||
|
sort: [ { rank: asc } ]
|
||||||
|
script_fields:
|
||||||
|
field:
|
||||||
|
script:
|
||||||
|
source: "String cat = ''; for (String s : field('match_only_text')) { cat += s; } cat + field('match_only_text').size();"
|
||||||
|
- match: { hits.hits.0.fields.field.0: "Lots of text.1" }
|
||||||
|
- match: { hits.hits.1.fields.field.0: "0" }
|
||||||
|
- match: { hits.hits.2.fields.field.0: "Lots of text.SOOOOO much texteven more text3" }
|
||||||
|
|
||||||
---
|
---
|
||||||
"version and sequence number":
|
"version and sequence number":
|
||||||
- do:
|
- do:
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.index.analysis.IndexAnalyzers;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.index.fielddata.FieldDataContext;
|
import org.elasticsearch.index.fielddata.FieldDataContext;
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
|
import org.elasticsearch.index.fielddata.SourceValueFetcherSortedBinaryIndexFieldData;
|
||||||
import org.elasticsearch.index.mapper.DocumentParserContext;
|
import org.elasticsearch.index.mapper.DocumentParserContext;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MapperBuilderContext;
|
import org.elasticsearch.index.mapper.MapperBuilderContext;
|
||||||
|
@ -44,6 +45,8 @@ import org.elasticsearch.index.mapper.TextParams;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
import org.elasticsearch.index.mapper.ValueFetcher;
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.index.query.SearchExecutionContext;
|
import org.elasticsearch.index.query.SearchExecutionContext;
|
||||||
|
import org.elasticsearch.script.field.TextDocValuesField;
|
||||||
|
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -276,6 +279,16 @@ public class MatchOnlyTextFieldMapper extends FieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
|
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
|
||||||
|
if (fieldDataContext.fielddataOperation() == FielddataOperation.SCRIPT) {
|
||||||
|
return new SourceValueFetcherSortedBinaryIndexFieldData.Builder(
|
||||||
|
name(),
|
||||||
|
CoreValuesSourceType.KEYWORD,
|
||||||
|
SourceValueFetcher.toString(fieldDataContext.sourcePathsLookup().apply(name())),
|
||||||
|
fieldDataContext.lookupSupplier().get().source(),
|
||||||
|
TextDocValuesField::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException(CONTENT_TYPE + " fields do not support sorting and aggregations");
|
throw new IllegalArgumentException(CONTENT_TYPE + " fields do not support sorting and aggregations");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.script.field;
|
||||||
|
|
||||||
|
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
|
||||||
|
|
||||||
|
public class MatchOnlyTextDocValuesField extends BaseKeywordDocValuesField {
|
||||||
|
|
||||||
|
public MatchOnlyTextDocValuesField(SortedBinaryDocValues input, String name) {
|
||||||
|
super(input, name);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue