Add index-time scripts to IP field mapper (#71617)

This commit allows you to set 'script' and 'on_script_error' parameters
on IP field mappers, meaning that runtime IP fields can be made indexed
simply by moving their definitions from the runtime section of the mappings
to the properties section.
This commit is contained in:
Alan Woodward 2021-04-13 13:40:10 +01:00 committed by GitHub
parent 57e6c78a52
commit 67db2538f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 386 additions and 17 deletions

View File

@ -54,7 +54,8 @@ The following parameters are accepted by `ip` fields:
<<ignore-malformed,`ignore_malformed`>>::
If `true`, malformed IP addresses are ignored. If `false` (default), malformed
IP addresses throw an exception and reject the whole document.
IP addresses throw an exception and reject the whole document. Note that this
cannot be set if the `script` parameter is used.
<<mapping-index,`index`>>::
@ -63,7 +64,28 @@ The following parameters are accepted by `ip` fields:
<<null-value,`null_value`>>::
Accepts an IPv4 or IPv6 value which is substituted for any explicit `null` values.
Defaults to `null`, which means the field is treated as missing.
Defaults to `null`, which means the field is treated as missing. Note that
this cannot be set if the `script` parameter is used.
`on_script_error`::
Defines what to do if the script defined by the `script` parameter
throws an error at indexing time. Accepts `reject` (default), which
will cause the entire document to be rejected, and `ignore`, which
will register the field in the document's
<<mapping-ignored-field,`_ignored`>> metadata field and continue
indexing. This parameter can only be set if the `script` field is
also set.
`script`::
If this parameter is set, then the field will index values generated
by this script, rather than reading the values directly from the
source. If a value is set for this field on the input document, then
the document will be rejected with an error.
Scripts are in the same format as their
<<runtime-mapping-fields,runtime equivalent>>, and should emit strings
containing IPv4 or IPv6 formatted addresses.
<<mapping-store,`store`>>::

View File

@ -0,0 +1,161 @@
---
setup:
- do:
indices.create:
index: http_logs
body:
settings:
number_of_shards: 1
number_of_replicas: 0
mappings:
properties:
ip:
type: ip
script:
source: |
Matcher m = /([^ ]+) .+/.matcher(doc["message"].value);
if (m.matches()) {
emit(m.group(1));
}
# Test fetching from _source
ip_from_source:
type: ip
script:
source: |
Matcher m = /([^ ]+) .+/.matcher(params._source.message);
if (m.matches()) {
emit(m.group(1));
}
# Test emitting many values
ip_many:
type: ip
script:
source: |
String m = doc["message"].value;
int end = m.indexOf(" ");
end = m.lastIndexOf(".", end);
String stem = m.substring(0, end + 1);
for (int i = 0; i < 5; i++) {
emit(stem + i);
}
timestamp:
type: date
message:
type: keyword
- do:
bulk:
index: http_logs
refresh: true
body: |
{"index":{}}
{"timestamp": "1998-04-30T14:30:17-05:00", "message" : "40.135.0.0 - - [1998-04-30T14:30:17-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp": "1998-04-30T14:30:53-05:00", "message" : "232.0.0.0 - - [1998-04-30T14:30:53-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp": "1998-04-30T14:31:12-05:00", "message" : "26.1.0.0 - - [1998-04-30T14:31:12-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp": "1998-04-30T14:31:19-05:00", "message" : "247.37.0.0 - - [1998-04-30T14:31:19-05:00] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"}
{"index":{}}
{"timestamp": "1998-04-30T14:31:22-05:00", "message" : "247.37.0.0 - - [1998-04-30T14:31:22-05:00] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"}
{"index":{}}
{"timestamp": "1998-04-30T14:31:27-05:00", "message" : "252.0.0.0 - - [1998-04-30T14:31:27-05:00] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
---
"get mapping":
- do:
indices.get_mapping:
index: http_logs
- match: {http_logs.mappings.properties.ip.type: ip }
- match:
http_logs.mappings.properties.ip.script.source: |
Matcher m = /([^ ]+) .+/.matcher(doc["message"].value);
if (m.matches()) {
emit(m.group(1));
}
- match: {http_logs.mappings.properties.ip.script.lang: painless }
---
"fetch fields":
- do:
search:
index: http_logs
body:
sort: timestamp
fields: [ip, ip_from_source, ip_many]
- match: {hits.total.value: 6}
- match: {hits.hits.0.fields.ip: ["40.135.0.0"] }
- match: {hits.hits.0.fields.ip_from_source: ["40.135.0.0"] }
- match:
hits.hits.0.fields.ip_many:
- 40.135.0.0
- 40.135.0.1
- 40.135.0.2
- 40.135.0.3
- 40.135.0.4
---
"docvalue_fields":
- do:
search:
index: http_logs
body:
sort: timestamp
docvalue_fields: [ip, ip_from_source, ip_many]
- match: {hits.total.value: 6}
- match: {hits.hits.0.fields.ip: ["40.135.0.0"] }
- match: {hits.hits.0.fields.ip_from_source: ["40.135.0.0"] }
- match:
hits.hits.0.fields.ip_many:
- 40.135.0.0
- 40.135.0.1
- 40.135.0.2
- 40.135.0.3
- 40.135.0.4
---
"terms agg":
- do:
search:
index: http_logs
body:
aggs:
ip:
terms:
field: ip
- match: {hits.total.value: 6}
- match: {aggregations.ip.buckets.0.key: 247.37.0.0}
- match: {aggregations.ip.buckets.0.doc_count: 2}
- match: {aggregations.ip.buckets.1.key: 26.1.0.0}
- match: {aggregations.ip.buckets.1.doc_count: 1}
---
"use in scripts":
- do:
search:
index: http_logs
body:
aggs:
ip:
terms:
script:
String v = doc['ip'].value;
return v.substring(0, v.indexOf('.'));
- match: {hits.total.value: 6}
- match: {aggregations.ip.buckets.0.key: '247'}
- match: {aggregations.ip.buckets.0.doc_count: 2}
- match: {aggregations.ip.buckets.1.key: '232'}
- match: {aggregations.ip.buckets.1.doc_count: 1}
---
"term query":
- do:
search:
index: http_logs
body:
query:
term:
ip: 252.0.0.0
- match: {hits.total.value: 1}
- match: {hits.hits.0._source.timestamp: "1998-04-30T14:31:27-05:00"}

View File

@ -11,6 +11,7 @@ package org.elasticsearch.index.mapper;
import org.apache.lucene.document.InetAddressPoint;
import org.apache.lucene.document.SortedSetDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
@ -26,8 +27,12 @@ import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.script.IpFieldScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptCompiler;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
import org.elasticsearch.search.lookup.FieldValues;
import org.elasticsearch.search.lookup.SearchLookup;
import java.io.IOException;
@ -38,6 +43,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Supplier;
@ -62,17 +68,31 @@ public class IpFieldMapper extends FieldMapper {
private final Parameter<String> nullValue
= Parameter.stringParam("null_value", false, m -> toType(m).nullValueAsString, null).acceptsNull();
private final Parameter<Script> script = Parameter.scriptParam(m -> toType(m).script);
private final Parameter<String> onScriptError = Parameter.onScriptErrorParam(m -> toType(m).onScriptError, script);
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
private final boolean ignoreMalformedByDefault;
private final Version indexCreatedVersion;
private final ScriptCompiler scriptCompiler;
public Builder(String name, boolean ignoreMalformedByDefault, Version indexCreatedVersion) {
public Builder(String name, ScriptCompiler scriptCompiler, boolean ignoreMalformedByDefault, Version indexCreatedVersion) {
super(name);
this.scriptCompiler = Objects.requireNonNull(scriptCompiler);
this.ignoreMalformedByDefault = ignoreMalformedByDefault;
this.indexCreatedVersion = indexCreatedVersion;
this.ignoreMalformed
= Parameter.boolParam("ignore_malformed", true, m -> toType(m).ignoreMalformed, ignoreMalformedByDefault);
this.script.precludesParameters(nullValue, ignoreMalformed);
this.script.setValidator(s -> {
if (s != null && indexed.get() == false && hasDocValues.get() == false) {
throw new MapperParsingException("Cannot define script on field with index:false and doc_values:false");
}
if (s != null && multiFieldsBuilder.hasMultiFields()) {
throw new MapperParsingException("Cannot define multifields on a field with a script");
}
});
}
Builder nullValue(String nullValue) {
@ -98,16 +118,27 @@ public class IpFieldMapper extends FieldMapper {
}
}
private FieldValues<InetAddress> scriptValues() {
if (this.script.get() == null) {
return null;
}
IpFieldScript.Factory factory = scriptCompiler.compile(this.script.get(), IpFieldScript.CONTEXT);
return factory == null ? null : (lookup, ctx, doc, consumer) -> factory
.newFactory(name, script.get().getParams(), lookup)
.newInstance(ctx)
.runForDoc(doc, consumer);
}
@Override
protected List<Parameter<?>> getParameters() {
return List.of(indexed, hasDocValues, stored, ignoreMalformed, nullValue, meta);
return List.of(indexed, hasDocValues, stored, ignoreMalformed, nullValue, script, onScriptError, meta);
}
@Override
public IpFieldMapper build(ContentPath contentPath) {
return new IpFieldMapper(name,
new IpFieldType(buildFullName(contentPath), indexed.getValue(), stored.getValue(),
hasDocValues.getValue(), parseNullValue(), meta.getValue()),
hasDocValues.getValue(), parseNullValue(), scriptValues(), meta.getValue()),
multiFieldsBuilder.build(this, contentPath), copyTo.build(), this);
}
@ -115,21 +146,23 @@ public class IpFieldMapper extends FieldMapper {
public static final TypeParser PARSER = new TypeParser((n, c) -> {
boolean ignoreMalformedByDefault = IGNORE_MALFORMED_SETTING.get(c.getSettings());
return new Builder(n, ignoreMalformedByDefault, c.indexVersionCreated());
return new Builder(n, c.scriptCompiler(), ignoreMalformedByDefault, c.indexVersionCreated());
});
public static final class IpFieldType extends SimpleMappedFieldType {
private final InetAddress nullValue;
private final FieldValues<InetAddress> scriptValues;
public IpFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
InetAddress nullValue, Map<String, String> meta) {
InetAddress nullValue, FieldValues<InetAddress> scriptValues, Map<String, String> meta) {
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.nullValue = nullValue;
this.scriptValues = scriptValues;
}
public IpFieldType(String name) {
this(name, true, false, true, null, Collections.emptyMap());
this(name, true, false, true, null, null, Collections.emptyMap());
}
@Override
@ -153,6 +186,9 @@ public class IpFieldMapper extends FieldMapper {
if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
}
if (scriptValues != null) {
return FieldValues.valueFetcher(scriptValues, v -> InetAddresses.toAddrString((InetAddress)v), context);
}
return new SourceValueFetcher(name(), context, nullValue) {
@Override
protected Object parseSourceValue(Object value) {
@ -348,13 +384,17 @@ public class IpFieldMapper extends FieldMapper {
private final boolean ignoreMalformedByDefault;
private final Version indexCreatedVersion;
private final Script script;
private final FieldValues<InetAddress> scriptValues;
private final ScriptCompiler scriptCompiler;
private IpFieldMapper(
String simpleName,
MappedFieldType mappedFieldType,
MultiFields multiFields,
CopyTo copyTo,
Builder builder) {
super(simpleName, mappedFieldType, multiFields, copyTo);
super(simpleName, mappedFieldType, multiFields, copyTo, builder.script.get() != null, builder.onScriptError.get());
this.ignoreMalformedByDefault = builder.ignoreMalformedByDefault;
this.indexed = builder.indexed.getValue();
this.hasDocValues = builder.hasDocValues.getValue();
@ -363,6 +403,9 @@ public class IpFieldMapper extends FieldMapper {
this.nullValue = builder.parseNullValue();
this.nullValueAsString = builder.nullValue.getValue();
this.indexCreatedVersion = builder.indexCreatedVersion;
this.script = builder.script.get();
this.scriptValues = builder.scriptValues();
this.scriptCompiler = builder.scriptCompiler;
}
boolean ignoreMalformed() {
@ -413,6 +456,10 @@ public class IpFieldMapper extends FieldMapper {
}
}
indexValue(context, address);
}
private void indexValue(ParseContext context, InetAddress address) {
if (indexed) {
context.doc().add(new InetAddressPoint(fieldType().name(), address));
}
@ -426,9 +473,14 @@ public class IpFieldMapper extends FieldMapper {
}
}
@Override
protected void indexScriptValues(SearchLookup searchLookup, LeafReaderContext readerContext, int doc, ParseContext parseContext) {
this.scriptValues.valuesForDoc(searchLookup, readerContext, doc, value -> indexValue(parseContext, value));
}
@Override
public FieldMapper.Builder getMergeBuilder() {
return new Builder(simpleName(), ignoreMalformedByDefault, indexCreatedVersion).init(this);
return new Builder(simpleName(), scriptCompiler, ignoreMalformedByDefault, indexCreatedVersion).init(this);
}
}

View File

@ -21,6 +21,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Consumer;
/**
* Script producing IP addresses. Unlike the other {@linkplain AbstractFieldScript}s
@ -66,6 +67,13 @@ public abstract class IpFieldScript extends AbstractFieldScript {
execute();
}
public final void runForDoc(int docId, Consumer<InetAddress> consumer) {
runForDoc(docId);
for (int i = 0; i < count; i++) {
consumer.accept(InetAddressPoint.decode(values[i].bytes));
}
}
/**
* Values from the last time {@link #runForDoc(int)} was called. This array
* is mutable and will change with the next call of {@link #runForDoc(int)}.
@ -97,7 +105,7 @@ public abstract class IpFieldScript extends AbstractFieldScript {
return count;
}
protected final void emit(String v) {
public final void emit(String v) {
checkMaxSize(count);
if (values.length < count + 1) {
values = ArrayUtil.grow(values, count + 1);

View File

@ -15,6 +15,7 @@ import org.elasticsearch.index.query.SearchExecutionContext;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Represents values for a given document
@ -37,6 +38,17 @@ public interface FieldValues<T> {
* @return the value fetcher
*/
static ValueFetcher valueFetcher(FieldValues<?> fieldValues, SearchExecutionContext context) {
return valueFetcher(fieldValues, v -> v, context);
}
/**
* Creates a {@link ValueFetcher} that fetches values from a {@link FieldValues} instance
* @param fieldValues the source of the values
* @param formatter a function to format the values
* @param context the search execution context
* @return the value fetcher
*/
static ValueFetcher valueFetcher(FieldValues<?> fieldValues, Function<Object, Object> formatter, SearchExecutionContext context) {
return new ValueFetcher() {
LeafReaderContext ctx;
@ -49,7 +61,7 @@ public interface FieldValues<T> {
public List<Object> fetchValues(SourceLookup lookup) {
List<Object> values = new ArrayList<>();
try {
fieldValues.valuesForDoc(context.lookup(), ctx, lookup.docId(), values::add);
fieldValues.valuesForDoc(context.lookup(), ctx, lookup.docId(), v -> values.add(formatter.apply(v)));
} catch (Exception e) {
// ignore errors - if they exist here then they existed at index time
// and so on_script_error must have been set to `ignore`

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.net.InetAddress;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
public class IpFieldMapperTests extends MapperTestCase {
@ -213,4 +214,25 @@ public class IpFieldMapperTests extends MapperTestCase {
protected boolean dedupAfterFetch() {
return true;
}
public void testScriptAndPrecludedParameters() {
{
Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> {
b.field("type", "ip");
b.field("script", "test");
b.field("null_value", 7);
})));
assertThat(e.getMessage(),
equalTo("Failed to parse mapping: Field [null_value] cannot be set in conjunction with field [script]"));
}
{
Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> {
b.field("type", "ip");
b.field("script", "test");
b.field("ignore_malformed", "true");
})));
assertThat(e.getMessage(),
equalTo("Failed to parse mapping: Field [ignore_malformed] cannot be set in conjunction with field [script]"));
}
}
}

View File

@ -15,6 +15,7 @@ import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.Version;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.script.ScriptCompiler;
import java.io.IOException;
import java.net.InetAddress;
@ -63,7 +64,7 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
prefix = ip + "/16";
assertEquals(InetAddressPoint.newPrefixQuery("field", InetAddresses.forString(ip), 16), ft.termQuery(prefix, null));
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, Collections.emptyMap());
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, null, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.termQuery("::1", null));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -166,7 +167,7 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
InetAddresses.forString("2001:db8::")),
ft.rangeQuery("::ffff:c0a8:107", "2001:db8::", true, true, null, null, null, null));
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, Collections.emptyMap());
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, null, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.rangeQuery("::1", "2001::", true, true, null, null, null, null));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -174,12 +175,12 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
public void testFetchSourceValue() throws IOException {
MappedFieldType mapper
= new IpFieldMapper.Builder("field", true, Version.CURRENT).build(new ContentPath()).fieldType();
= new IpFieldMapper.Builder("field", ScriptCompiler.NONE, true, Version.CURRENT).build(new ContentPath()).fieldType();
assertEquals(List.of("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8::2:1"));
assertEquals(List.of("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8:0:0:0:0:2:1"));
assertEquals(List.of("::1"), fetchSourceValue(mapper, "0:0:0:0:0:0:0:1"));
MappedFieldType nullValueMapper = new IpFieldMapper.Builder("field", true, Version.CURRENT)
MappedFieldType nullValueMapper = new IpFieldMapper.Builder("field", ScriptCompiler.NONE, true, Version.CURRENT)
.nullValue("2001:db8:0:0:0:0:2:7")
.build(new ContentPath())
.fieldType();

View File

@ -0,0 +1,90 @@
/*
* 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.index.mapper;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.LeafReaderContext;
import org.elasticsearch.script.IpFieldScript;
import org.elasticsearch.search.lookup.SearchLookup;
import java.util.Map;
import java.util.function.Consumer;
public class IpScriptMapperTests extends MapperScriptTestCase<IpFieldScript.Factory> {
private static IpFieldScript.Factory factory(Consumer<IpFieldScript> executor) {
return new IpFieldScript.Factory() {
@Override
public IpFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
return new IpFieldScript.LeafFactory() {
@Override
public IpFieldScript newInstance(LeafReaderContext ctx) {
return new IpFieldScript(fieldName, params, searchLookup, ctx) {
@Override
public void execute() {
executor.accept(this);
}
};
}
};
}
};
}
@Override
protected String type() {
return "ip";
}
@Override
protected IpFieldScript.Factory serializableScript() {
return factory(s -> {});
}
@Override
protected IpFieldScript.Factory errorThrowingScript() {
return factory(s -> {
throw new UnsupportedOperationException("Oops");
});
}
@Override
protected IpFieldScript.Factory singleValueScript() {
return factory(s -> s.emit("::1"));
}
@Override
protected IpFieldScript.Factory multipleValuesScript() {
return factory(s -> {
s.emit("::1");
s.emit("::2");
});
}
@Override
protected void assertMultipleValues(IndexableField[] fields) {
assertEquals(4, fields.length);
assertEquals("InetAddressPoint <field:[0:0:0:0:0:0:0:1]>", fields[0].toString());
assertEquals("docValuesType=SORTED_SET<field:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]>", fields[1].toString());
assertEquals("InetAddressPoint <field:[0:0:0:0:0:0:0:2]>", fields[2].toString());
assertEquals("docValuesType=SORTED_SET<field:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2]>", fields[3].toString());
}
@Override
protected void assertDocValuesDisabled(IndexableField[] fields) {
assertEquals(1, fields.length);
assertEquals("InetAddressPoint <field:[0:0:0:0:0:0:0:1]>", fields[0].toString());
}
@Override
protected void assertIndexDisabled(IndexableField[] fields) {
assertEquals(1, fields.length);
assertEquals("docValuesType=SORTED_SET<field:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]>", fields[0].toString());
}
}

View File

@ -1080,7 +1080,8 @@ public class TermsAggregatorTests extends AggregatorTestCase {
}
public void testIpField() throws Exception {
MappedFieldType fieldType = new IpFieldMapper.IpFieldType("field", randomBoolean(), false, true, null, Collections.emptyMap());
MappedFieldType fieldType
= new IpFieldMapper.IpFieldType("field", randomBoolean(), false, true, null, null, Collections.emptyMap());
testCase(new TermsAggregationBuilder("_name").field("field"), new MatchAllDocsQuery(), iw -> {
Document document = new Document();
InetAddress point = InetAddresses.forString("192.168.100.42");