Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d0c9a2e
copy patternedtext directory from prototype
parkertimmins Jun 6, 2025
78ef582
Remove timestamp and optimized args
parkertimmins Jun 6, 2025
6bb95ac
copy tests from prototype
parkertimmins Jun 11, 2025
ad728f3
Remove all token type specific test cases
parkertimmins Jun 11, 2025
a97bbc4
Fix bug introduced while moving to all shared args
parkertimmins Jun 11, 2025
3a0e349
index original value
parkertimmins Jun 11, 2025
cda6b0a
Remove type specific handling from tests
parkertimmins Jun 11, 2025
30ae746
[CI] Auto commit changes from spotless
Jun 11, 2025
387757d
A few more changes from prototype
parkertimmins Jun 11, 2025
03b9fde
add messages with arguments to yaml tests
parkertimmins Jun 11, 2025
f9344bf
More yaml test updates
parkertimmins Jun 12, 2025
e4d4830
[CI] Auto commit changes from spotless
Jun 12, 2025
fca0f83
Change to BinaryDocValues
parkertimmins Jun 13, 2025
f9b030b
[CI] Auto commit changes from spotless
Jun 13, 2025
4429474
address some pr feedback
parkertimmins Jun 13, 2025
10147ad
remove unneeded change
parkertimmins Jun 13, 2025
4a3ba41
Merge branch 'main' into parker/pattern-text-initial-version
parkertimmins Jun 18, 2025
b7450c2
Make patterned_text not aggregatable
parkertimmins Jun 18, 2025
8efac46
apply patch to simplify fielddata
parkertimmins Jun 19, 2025
cd2f9aa
Fixes to fielddata and valuefetcher
parkertimmins Jun 19, 2025
906ca11
removed wrong yaml test
parkertimmins Jun 20, 2025
0815760
move patternedtext into logsdb
parkertimmins Jun 21, 2025
6856d2d
more changes to move into logsdb
parkertimmins Jun 21, 2025
4b63ed0
Add patterned_text feature_flag
parkertimmins Jun 24, 2025
fa022e6
Update docs/changelog/129292.yaml
parkertimmins Jun 24, 2025
8cd70fd
Merge branch 'main' into parker/pattern-text-initial-version
parkertimmins Jun 24, 2025
526fef1
Delete docs/changelog/129292.yaml
parkertimmins Jun 24, 2025
39e9d88
Throw exception if multiple messages in document
parkertimmins Jun 24, 2025
eb4212f
[CI] Auto commit changes from spotless
Jun 24, 2025
e026a5c
disable array tests since multiple values disallowed
parkertimmins Jun 24, 2025
a2bc5fa
Add doc values tests
parkertimmins Jun 24, 2025
f0da074
[CI] Auto commit changes from spotless
Jun 24, 2025
4e0c337
add comment
parkertimmins Jun 25, 2025
109afd4
Merge branch 'main' into parker/pattern-text-initial-version
parkertimmins Jun 25, 2025
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
2 changes: 2 additions & 0 deletions modules/mapper-extras/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
requires org.apache.lucene.core;
requires org.apache.lucene.memory;
requires org.apache.lucene.queries;

exports org.elasticsearch.index.mapper.extras;
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public MatchOnlyTextFieldType(
super(name, true, false, false, tsi, meta);
this.indexAnalyzer = Objects.requireNonNull(indexAnalyzer);
this.textFieldType = new TextFieldType(name, isSyntheticSource);
this.originalName = isSyntheticSource ? name() + "._original" : null;
this.originalName = isSyntheticSource ? name + "._original" : null;
}

public MatchOnlyTextFieldType(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,10 +634,10 @@ public String toString() {
}
}

private static class SingletonOrdinals extends BlockDocValuesReader {
public static class SingletonOrdinals extends BlockDocValuesReader {
private final SortedDocValues ordinals;

SingletonOrdinals(SortedDocValues ordinals) {
public SingletonOrdinals(SortedDocValues ordinals) {
this.ordinals = ordinals;
}

Expand Down Expand Up @@ -692,10 +692,10 @@ public String toString() {
}
}

private static class Ordinals extends BlockDocValuesReader {
public static class Ordinals extends BlockDocValuesReader {
private final SortedSetDocValues ordinals;

Ordinals(SortedSetDocValues ordinals) {
public Ordinals(SortedSetDocValues ordinals) {
this.ordinals = ordinals;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ private FieldContext contextBuilders(
if (fieldNameContainsWildcards) {
if (fieldType.typeName().equals(TextFieldMapper.CONTENT_TYPE) == false
&& fieldType.typeName().equals(KeywordFieldMapper.CONTENT_TYPE) == false
&& fieldType.typeName().equals("match_only_text") == false) {
&& fieldType.typeName().equals("match_only_text") == false
&& fieldType.typeName().equals("patterned_text") == false) {
continue;
}
if (highlighter.canHighlight(fieldType) == false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@
*/
package org.elasticsearch.index.mapper;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.DocValuesSkipIndexType;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.VectorEncoding;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.tests.index.RandomIndexWriter;
import org.elasticsearch.index.IndexVersion;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.search.lookup.FieldLookup;
Expand All @@ -32,6 +39,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -71,6 +79,24 @@ public static List<?> fetchSourceValue(MappedFieldType fieldType, Object sourceV
return fetcher.fetchValues(source, -1, new ArrayList<>());
}

public static List<?> fetchDocValues(MappedFieldType fieldType, Supplier<Document> documentSupplier) throws IOException {
IndexWriterConfig iwc = new IndexWriterConfig(null);
try (Directory dir = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc)) {
iw.addDocument(documentSupplier.get());
try (DirectoryReader reader = iw.getReader()) {
IndexSearcher searcher = newSearcher(reader);
LeafReaderContext context = searcher.getIndexReader().leaves().get(0);
SearchExecutionContext searchExecutionContext = mock(SearchExecutionContext.class);
when(searchExecutionContext.getForField(fieldType, MappedFieldType.FielddataOperation.SEARCH)).thenReturn(
fieldType.fielddataBuilder(null).build(null, null)
);
ValueFetcher valueFetcher = fieldType.valueFetcher(searchExecutionContext, null);
valueFetcher.setNextReader(context);
return valueFetcher.fetchValues(null, 0, new ArrayList<>());
}
}
}

public static List<?> fetchSourceValues(MappedFieldType fieldType, Object... values) throws IOException {
String field = fieldType.name();
SearchExecutionContext searchExecutionContext = mock(SearchExecutionContext.class);
Expand Down
30 changes: 30 additions & 0 deletions x-pack/plugin/mapper-patterned-text/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

apply plugin: 'elasticsearch.internal-es-plugin'
apply plugin: 'elasticsearch.internal-yaml-rest-test'

esplugin {
name = 'patterned-text'
description = 'Module for the patterned_text field type.'
classname ='org.elasticsearch.xpack.patternedtext.PatternedTextMapperPlugin'
extendedPlugins = ['x-pack-core']
}
base {
archivesName = 'x-pack-patterned-text'
}

dependencies {
compileOnly project(path: xpackModule('core'))
implementation project(':modules:mapper-extras')
}

if (buildParams.getSnapshotBuild() == false) {
tasks.named("test").configure {
systemProperty 'es.index_mode_feature_flag_registered', 'true'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.patternedtext;

import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.index.SortedSetDocValues;
import org.elasticsearch.index.mapper.BlockDocValuesReader;

import java.io.IOException;

public class PatternedTextBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader {

private final String name;
private final String templateFieldName;
private final String argsFieldName;

PatternedTextBlockLoader(String name, String templateFieldName, String argsFieldName) {
this.name = name;
this.templateFieldName = templateFieldName;
this.argsFieldName = argsFieldName;
}

@Override
public BytesRefBuilder builder(BlockFactory factory, int expectedCount) {
return factory.bytesRefs(expectedCount);
}

@Override
public AllReader reader(LeafReaderContext context) throws IOException {
SortedSetDocValues combinedDocValues = ordinals(context);
if (combinedDocValues != null) {
SortedDocValues singleton = DocValues.unwrapSingleton(combinedDocValues);
if (singleton != null) {
return new BlockDocValuesReader.SingletonOrdinals(singleton);
}
return new BlockDocValuesReader.Ordinals(combinedDocValues);
}
return new ConstantNullsReader();
}

@Override
public boolean supportsOrdinals() {
return true;
}

@Override
public SortedSetDocValues ordinals(LeafReaderContext context) throws IOException {
return PatternedTextDocValues.from(context.reader(), templateFieldName, argsFieldName);
}

@Override
public String toString() {
return "PatternedTextBlockLoader[" + name + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.patternedtext;

import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.util.BytesRef;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class PatternedTextDocValues extends SortedSetDocValues {
private final SortedSetDocValues templateDocValues;
private final SortedSetDocValues argsDocValues;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be SortedDocValues. Since there is only args value per document? (all values are concatenated?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, there should only be one template and one concatenated args per doc


PatternedTextDocValues(SortedSetDocValues templateDocValues, SortedSetDocValues argsDocValues) {
this.templateDocValues = templateDocValues;
this.argsDocValues = argsDocValues;
}

static PatternedTextDocValues from(LeafReader leafReader, String templateFieldName, String argsFieldName) throws IOException {
SortedSetDocValues templateDocValues = DocValues.getSortedSet(leafReader, templateFieldName);
if (templateDocValues.getValueCount() == 0) {
return null;
}

SortedSetDocValues argsDocValues = DocValues.getSortedSet(leafReader, argsFieldName);
return new PatternedTextDocValues(templateDocValues, argsDocValues);
}

@Override
public long nextOrd() throws IOException {
return templateDocValues.nextOrd();
}

@Override
public int docValueCount() {
return templateDocValues.docValueCount();
}

@Override
public BytesRef lookupOrd(long l) throws IOException {
return new BytesRef(lookupOrdAsString(l));
}

String lookupOrdAsString(long l) throws IOException {
String template = templateDocValues.lookupOrd(l).utf8ToString();
int argsCount = PatternedTextValueProcessor.countArgs(template);
List<String> args = new ArrayList<>(argsCount);
if (argsCount > 0) {
var mergedArgs = argsDocValues.lookupOrd(argsDocValues.nextOrd());
PatternedTextValueProcessor.decodeRemainingArgs(args, mergedArgs.utf8ToString());
}
return PatternedTextValueProcessor.merge(new PatternedTextValueProcessor.Parts(template, args));
}

@Override
public long getValueCount() {
return templateDocValues.getValueCount();
}

@Override
public boolean advanceExact(int i) throws IOException {
argsDocValues.advanceExact(i);
return templateDocValues.advanceExact(i);
}

@Override
public int docID() {
return templateDocValues.docID();
}

@Override
public int nextDoc() throws IOException {
return templateDocValues.nextDoc();
}

@Override
public int advance(int i) throws IOException {
return templateDocValues.advance(i);
}

@Override
public long cost() {
return templateDocValues.cost() + argsDocValues.cost();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.patternedtext;

import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.script.field.BaseKeywordDocValuesField;

public class PatternedTextDocValuesField extends BaseKeywordDocValuesField {
public PatternedTextDocValuesField(SortedBinaryDocValues input, String name) {
super(input, name);
}
}
Loading