Skip to content

Commit

Permalink
Add source fallback support for match_only_text mapped type (#89473)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jdconrad committed Aug 22, 2022
1 parent b15f6dd commit 58fafe2
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 1 deletion.
5 changes: 5 additions & 0 deletions docs/changelog/89473.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 89473
summary: Add source fallback support for `match_only_text` mapped type
area: Mapping
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ setup:
fielddata: true
text_no_field_data:
type: text
match_only_text:
type: match_only_text
token_count:
type: token_count
analyzer: standard
Expand Down Expand Up @@ -125,6 +127,7 @@ setup:
scaled_float_no_doc_values: 3.14
text: "Lots of text."
text_no_field_data: "Lots of text."
match_only_text: "Lots of text."
token_count: count all these words please

- do:
Expand Down Expand Up @@ -169,7 +172,7 @@ setup:
scaled_float_no_doc_values: [2.5, -3.5]
text: ["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:
indices.refresh: {}
Expand Down Expand Up @@ -3234,6 +3237,136 @@ setup:
- match: { hits.hits.1.fields.field.0: "0" }
- 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":
- do:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.fielddata.FieldDataContext;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.SourceValueFetcherSortedBinaryIndexFieldData;
import org.elasticsearch.index.mapper.DocumentParserContext;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperBuilderContext;
Expand All @@ -44,6 +45,8 @@
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.ValueFetcher;
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 java.io.IOException;
Expand Down Expand Up @@ -276,6 +279,16 @@ public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions,

@Override
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");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 58fafe2

Please sign in to comment.