Skip to content

Exclude doc-value-only fields from all fields queries #82712

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/changelog/82712.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 82712
summary: Exclude doc-value-only fields from all fields queries
area: Search
type: enhancement
issues:
- 82710
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,8 @@ static Map<String, Float> resolveMappingFields(
) {
Map<String, Float> resolvedFields = new HashMap<>();
for (Map.Entry<String, Float> fieldEntry : fieldsAndWeights.entrySet()) {
boolean allField = Regex.isMatchAllPattern(fieldEntry.getKey());
boolean multiField = Regex.isSimpleMatchPattern(fieldEntry.getKey());
float weight = fieldEntry.getValue() == null ? 1.0f : fieldEntry.getValue();
Map<String, Float> fieldMap = resolveMappingField(
context,
fieldEntry.getKey(),
weight,
multiField == false,
allField == false,
fieldSuffix
);
Map<String, Float> fieldMap = resolveMappingField(context, fieldEntry.getKey(), weight, fieldSuffix);

for (Map.Entry<String, Float> field : fieldMap.entrySet()) {
float boost = field.getValue();
Expand All @@ -104,21 +95,13 @@ static Map<String, Float> resolveMappingFields(
* @param context The context of the query
* @param fieldOrPattern The field name or the pattern to resolve
* @param weight The weight for the field
* @param acceptAllTypes Whether all field type should be added when a pattern is expanded.
* If false, only searchable field types are added.
* @param acceptMetadataField Whether metadata fields should be added when a pattern is expanded.
* @param fieldSuffix The suffix name to add to the expanded field names if a mapping exists for that name.
* The original name of the field is kept if adding the suffix to the field name does not point to a valid field
* in the mapping.
*/
static Map<String, Float> resolveMappingField(
SearchExecutionContext context,
String fieldOrPattern,
float weight,
boolean acceptAllTypes,
boolean acceptMetadataField,
String fieldSuffix
) {
static Map<String, Float> resolveMappingField(SearchExecutionContext context, String fieldOrPattern, float weight, String fieldSuffix) {
boolean allField = Regex.isMatchAllPattern(fieldOrPattern);
boolean wildcard = Regex.isSimpleMatchPattern(fieldOrPattern);
Set<String> allFields = context.getMatchingFieldNames(fieldOrPattern);
Map<String, Float> fields = new HashMap<>();

Expand All @@ -128,12 +111,12 @@ static Map<String, Float> resolveMappingField(
}

MappedFieldType fieldType = context.getFieldType(fieldName);
if (acceptMetadataField == false && fieldType.name().startsWith("_")) {
// Ignore metadata fields
if (allField && (fieldType.name().startsWith("_") || fieldType.isIndexed() == false)) {
// Ignore metadata fields, runtime fields and doc-value-only fields
continue;
}

if (acceptAllTypes == false) {
if (wildcard) {
if (fieldType.getTextSearchInfo() == TextSearchInfo.NONE || fieldType.mayExistInIndex(context) == false) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public QueryStringQueryParser(SearchExecutionContext context, Map<String, Float>
* @param lenient If set to `true` will cause format based failures (like providing text to a numeric field) to be ignored.
*/
public QueryStringQueryParser(SearchExecutionContext context, boolean lenient) {
this(context, "*", resolveMappingField(context, "*", 1.0f, false, false, null), lenient);
this(context, "*", resolveMappingField(context, "*", 1.0f, null), lenient);
}

private QueryStringQueryParser(
Expand Down Expand Up @@ -264,22 +264,7 @@ private Query applyBoost(Query q, Float boost) {
private Map<String, Float> extractMultiFields(String field, boolean quoted) {
Map<String, Float> extractedFields;
if (field != null) {
boolean allFields = Regex.isMatchAllPattern(field);
if (allFields && this.field != null && this.field.equals(field)) {
// "*" is the default field
extractedFields = fieldsAndWeights;
}
boolean multiFields = Regex.isSimpleMatchPattern(field);
// Filters unsupported fields if a pattern is requested
// Filters metadata fields if all fields are requested
extractedFields = resolveMappingField(
context,
field,
1.0f,
allFields == false,
multiFields == false,
quoted ? quoteFieldSuffix : null
);
extractedFields = resolveMappingField(context, field, 1.0f, quoted ? quoteFieldSuffix : null);
} else if (quoted && quoteFieldSuffix != null) {
extractedFields = resolveMappingFields(context, fieldsAndWeights, quoteFieldSuffix);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,25 @@ public void testIndexedFieldResolution() throws IOException {
b.startObject("field1").field("type", "text").endObject();
b.startObject("field2").field("type", "text").endObject();
b.startObject("field3").field("type", "text").endObject();
b.startObject("field4").field("type", "long").field("index", false).endObject();
}));

ParsedDocument doc = mapperService.documentMapper().parse(source(b -> {
b.field("field1", "foo");
b.field("field2", "bar");
b.field("field4", 100);
}));

withLuceneIndex(mapperService, iw -> iw.addDocument(doc.rootDoc()), ir -> {

SearchExecutionContext context = createSearchExecutionContext(mapperService, new IndexSearcher(ir));

// field1 and field2 are present in the index, so they get resolved; field3 is in the mappings but
// not in the actual index, so it is ignored
// not in the actual index, so it is ignored; field4 is slow but still gets resolved because the
// wildcard request is partial
{
Map<String, Float> resolvedFields = QueryParserHelper.resolveMappingFields(context, Map.of("field*", 1.0f));
assertThat(resolvedFields.keySet(), containsInAnyOrder("field1", "field2"));
assertThat(resolvedFields.keySet(), containsInAnyOrder("field1", "field2", "field4"));
assertFalse(resolvedFields.containsKey("field3"));
}

Expand Down