Merge pull request #18658 from rmuir/jodaTime
improve date api for expressions/painless fields
This commit is contained in:
commit
0373c62a57
|
@ -27,6 +27,7 @@ import org.elasticsearch.common.geo.GeoPoint;
|
||||||
import org.elasticsearch.common.unit.DistanceUnit;
|
import org.elasticsearch.common.unit.DistanceUnit;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.joda.time.MutableDateTime;
|
import org.joda.time.MutableDateTime;
|
||||||
|
import org.joda.time.ReadableDateTime;
|
||||||
|
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -131,7 +132,7 @@ public interface ScriptDocValues<T> extends List<T> {
|
||||||
return Collections.unmodifiableList(this);
|
return Collections.unmodifiableList(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableDateTime getDate() {
|
public ReadableDateTime getDate() {
|
||||||
date.setMillis(getValue());
|
date.setMillis(getValue());
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,8 @@ import java.util.Set;
|
||||||
* <li>{@link org.joda.time.DateTimeUtils}</li>
|
* <li>{@link org.joda.time.DateTimeUtils}</li>
|
||||||
* <li>{@link org.joda.time.DateTimeZone}</li>
|
* <li>{@link org.joda.time.DateTimeZone}</li>
|
||||||
* <li>{@link org.joda.time.Instant}</li>
|
* <li>{@link org.joda.time.Instant}</li>
|
||||||
|
* <li>{@link org.joda.time.ReadableDateTime}</li>
|
||||||
|
* <li>{@link org.joda.time.ReadableInstant}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public final class ClassPermission extends BasicPermission {
|
public final class ClassPermission extends BasicPermission {
|
||||||
|
@ -102,7 +104,9 @@ public final class ClassPermission extends BasicPermission {
|
||||||
org.joda.time.DateTime.class.getName(),
|
org.joda.time.DateTime.class.getName(),
|
||||||
org.joda.time.DateTimeUtils.class.getName(),
|
org.joda.time.DateTimeUtils.class.getName(),
|
||||||
org.joda.time.DateTimeZone.class.getName(),
|
org.joda.time.DateTimeZone.class.getName(),
|
||||||
org.joda.time.Instant.class.getName()
|
org.joda.time.Instant.class.getName(),
|
||||||
|
org.joda.time.ReadableDateTime.class.getName(),
|
||||||
|
org.joda.time.ReadableInstant.class.getName()
|
||||||
)));
|
)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,6 +42,8 @@ scripts, simply set the `lang` parameter to `expression`.
|
||||||
|`doc['field_name'].empty` |A boolean indicating if the field has no
|
|`doc['field_name'].empty` |A boolean indicating if the field has no
|
||||||
values within the doc.
|
values within the doc.
|
||||||
|
|
||||||
|
|`doc['field_name'].length` |The number of values in this document.
|
||||||
|
|
||||||
|`doc['field_name'].min()` |The minimum value of the field in this document.
|
|`doc['field_name'].min()` |The minimum value of the field in this document.
|
||||||
|
|
||||||
|`doc['field_name'].max()` |The maximum value of the field in this document.
|
|`doc['field_name'].max()` |The maximum value of the field in this document.
|
||||||
|
@ -51,8 +53,6 @@ values within the doc.
|
||||||
|`doc['field_name'].avg()` |The average of the values in this document.
|
|`doc['field_name'].avg()` |The average of the values in this document.
|
||||||
|
|
||||||
|`doc['field_name'].sum()` |The sum of the values in this document.
|
|`doc['field_name'].sum()` |The sum of the values in this document.
|
||||||
|
|
||||||
|`doc['field_name'].count()` |The number of values in this document.
|
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
When a document is missing the field completely, by default the value will be treated as `0`.
|
When a document is missing the field completely, by default the value will be treated as `0`.
|
||||||
|
@ -69,27 +69,47 @@ For example: `doc['on_sale'].value ? doc['price'].value * 0.5 : doc['price'].val
|
||||||
[float]
|
[float]
|
||||||
=== Date field API
|
=== Date field API
|
||||||
Date fields are treated as the number of milliseconds since January 1, 1970 and
|
Date fields are treated as the number of milliseconds since January 1, 1970 and
|
||||||
support the Numeric Fields API above, with these additional methods:
|
support the Numeric Fields API above, plus access to some date-specific fields:
|
||||||
|
|
||||||
[cols="<,<",options="header",]
|
[cols="<,<",options="header",]
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|Expression |Description
|
|Expression |Description
|
||||||
|`doc['field_name'].getYear()` |Year component, e.g. `1970`.
|
|`doc['field_name'].date.centuryOfEra`|Century (1-2920000)
|
||||||
|
|
||||||
|`doc['field_name'].getMonth()` |Month component (0-11), e.g. `0` for January.
|
|`doc['field_name'].date.dayOfMonth`|Day (1-31), e.g. `1` for the first of the month.
|
||||||
|
|
||||||
|`doc['field_name'].getDayOfMonth()` |Day component, e.g. `1` for the first of the month.
|
|`doc['field_name'].date.dayOfWeek`|Day of the week (1-7), e.g. `1` for Monday.
|
||||||
|
|
||||||
|`doc['field_name'].getHourOfDay()` |Hour component (0-23)
|
|`doc['field_name'].date.dayOfYear`|Day of the year, e.g. `1` for January 1.
|
||||||
|
|
||||||
|`doc['field_name'].getMinutes()` |Minutes component (0-59)
|
|`doc['field_name'].date.era`|Era: `0` for BC, `1` for AD.
|
||||||
|
|
||||||
|`doc['field_name'].getSeconds()` |Seconds component (0-59)
|
|`doc['field_name'].date.hourOfDay`|Hour (0-23).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.millisOfDay`|Milliseconds within the day (0-86399999).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.millisOfSecond`|Milliseconds within the second (0-999).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.minuteOfDay`|Minute within the day (0-1439).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.minuteOfHour`|Minute within the hour (0-59).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.monthOfYear`|Month within the year (1-12), e.g. `1` for January.
|
||||||
|
|
||||||
|
|`doc['field_name'].date.secondOfDay`|Second within the day (0-86399).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.secondOfMinute`|Second within the minute (0-59).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.year`|Year (-292000000 - 292000000).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.yearOfCentury`|Year within the century (1-100).
|
||||||
|
|
||||||
|
|`doc['field_name'].date.yearOfEra`|Year within the era (1-292000000).
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
The following example shows the difference in years between the `date` fields date0 and date1:
|
The following example shows the difference in years between the `date` fields date0 and date1:
|
||||||
|
|
||||||
`doc['date1'].getYear() - doc['date0'].getYear()`
|
`doc['date1'].date.year - doc['date0'].date.year`
|
||||||
|
|
||||||
[float]
|
[float]
|
||||||
=== `geo_point` field API
|
=== `geo_point` field API
|
||||||
|
|
|
@ -35,14 +35,20 @@ final class DateField {
|
||||||
// supported variables
|
// supported variables
|
||||||
static final String VALUE_VARIABLE = "value";
|
static final String VALUE_VARIABLE = "value";
|
||||||
static final String EMPTY_VARIABLE = "empty";
|
static final String EMPTY_VARIABLE = "empty";
|
||||||
|
static final String LENGTH_VARIABLE = "length";
|
||||||
|
|
||||||
// supported methods
|
// supported methods
|
||||||
|
static final String GETVALUE_METHOD = "getValue";
|
||||||
|
static final String ISEMPTY_METHOD = "isEmpty";
|
||||||
|
static final String SIZE_METHOD = "size";
|
||||||
static final String MINIMUM_METHOD = "min";
|
static final String MINIMUM_METHOD = "min";
|
||||||
static final String MAXIMUM_METHOD = "max";
|
static final String MAXIMUM_METHOD = "max";
|
||||||
static final String AVERAGE_METHOD = "avg";
|
static final String AVERAGE_METHOD = "avg";
|
||||||
static final String MEDIAN_METHOD = "median";
|
static final String MEDIAN_METHOD = "median";
|
||||||
static final String SUM_METHOD = "sum";
|
static final String SUM_METHOD = "sum";
|
||||||
static final String COUNT_METHOD = "count";
|
static final String COUNT_METHOD = "count";
|
||||||
|
|
||||||
|
// date-specific
|
||||||
static final String GET_YEAR_METHOD = "getYear";
|
static final String GET_YEAR_METHOD = "getYear";
|
||||||
static final String GET_MONTH_METHOD = "getMonth";
|
static final String GET_MONTH_METHOD = "getMonth";
|
||||||
static final String GET_DAY_OF_MONTH_METHOD = "getDayOfMonth";
|
static final String GET_DAY_OF_MONTH_METHOD = "getDayOfMonth";
|
||||||
|
@ -56,6 +62,8 @@ final class DateField {
|
||||||
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
case EMPTY_VARIABLE:
|
case EMPTY_VARIABLE:
|
||||||
return new EmptyMemberValueSource(fieldData);
|
return new EmptyMemberValueSource(fieldData);
|
||||||
|
case LENGTH_VARIABLE:
|
||||||
|
return new CountMethodValueSource(fieldData);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Member variable [" + variable + "] does not exist for date field [" + fieldName + "].");
|
throw new IllegalArgumentException("Member variable [" + variable + "] does not exist for date field [" + fieldName + "].");
|
||||||
}
|
}
|
||||||
|
@ -63,6 +71,12 @@ final class DateField {
|
||||||
|
|
||||||
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
|
case GETVALUE_METHOD:
|
||||||
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
|
case ISEMPTY_METHOD:
|
||||||
|
return new EmptyMemberValueSource(fieldData);
|
||||||
|
case SIZE_METHOD:
|
||||||
|
return new CountMethodValueSource(fieldData);
|
||||||
case MINIMUM_METHOD:
|
case MINIMUM_METHOD:
|
||||||
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
case MAXIMUM_METHOD:
|
case MAXIMUM_METHOD:
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
package org.elasticsearch.script.expression;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.queries.function.ValueSource;
|
||||||
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
|
import org.elasticsearch.search.MultiValueMode;
|
||||||
|
import org.joda.time.ReadableDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expressions API for date objects (.date)
|
||||||
|
*/
|
||||||
|
final class DateObject {
|
||||||
|
// no instance
|
||||||
|
private DateObject() {}
|
||||||
|
|
||||||
|
// supported variables
|
||||||
|
static final String CENTURY_OF_ERA_VARIABLE = "centuryOfEra";
|
||||||
|
static final String DAY_OF_MONTH_VARIABLE = "dayOfMonth";
|
||||||
|
static final String DAY_OF_WEEK_VARIABLE = "dayOfWeek";
|
||||||
|
static final String DAY_OF_YEAR_VARIABLE = "dayOfYear";
|
||||||
|
static final String ERA_VARIABLE = "era";
|
||||||
|
static final String HOUR_OF_DAY_VARIABLE = "hourOfDay";
|
||||||
|
static final String MILLIS_OF_DAY_VARIABLE = "millisOfDay";
|
||||||
|
static final String MILLIS_OF_SECOND_VARIABLE = "millisOfSecond";
|
||||||
|
static final String MINUTE_OF_DAY_VARIABLE = "minuteOfDay";
|
||||||
|
static final String MINUTE_OF_HOUR_VARIABLE = "minuteOfHour";
|
||||||
|
static final String MONTH_OF_YEAR_VARIABLE = "monthOfYear";
|
||||||
|
static final String SECOND_OF_DAY_VARIABLE = "secondOfDay";
|
||||||
|
static final String SECOND_OF_MINUTE_VARIABLE = "secondOfMinute";
|
||||||
|
static final String WEEK_OF_WEEK_YEAR_VARIABLE = "weekOfWeekyear";
|
||||||
|
static final String WEEK_YEAR_VARIABLE = "weekyear";
|
||||||
|
static final String YEAR_VARIABLE = "year";
|
||||||
|
static final String YEAR_OF_CENTURY_VARIABLE = "yearOfCentury";
|
||||||
|
static final String YEAR_OF_ERA_VARIABLE = "yearOfEra";
|
||||||
|
|
||||||
|
// supported methods
|
||||||
|
static final String GETCENTURY_OF_ERA_METHOD = "getCenturyOfEra";
|
||||||
|
static final String GETDAY_OF_MONTH_METHOD = "getDayOfMonth";
|
||||||
|
static final String GETDAY_OF_WEEK_METHOD = "getDayOfWeek";
|
||||||
|
static final String GETDAY_OF_YEAR_METHOD = "getDayOfYear";
|
||||||
|
static final String GETERA_METHOD = "getEra";
|
||||||
|
static final String GETHOUR_OF_DAY_METHOD = "getHourOfDay";
|
||||||
|
static final String GETMILLIS_OF_DAY_METHOD = "getMillisOfDay";
|
||||||
|
static final String GETMILLIS_OF_SECOND_METHOD = "getMillisOfSecond";
|
||||||
|
static final String GETMINUTE_OF_DAY_METHOD = "getMinuteOfDay";
|
||||||
|
static final String GETMINUTE_OF_HOUR_METHOD = "getMinuteOfHour";
|
||||||
|
static final String GETMONTH_OF_YEAR_METHOD = "getMonthOfYear";
|
||||||
|
static final String GETSECOND_OF_DAY_METHOD = "getSecondOfDay";
|
||||||
|
static final String GETSECOND_OF_MINUTE_METHOD = "getSecondOfMinute";
|
||||||
|
static final String GETWEEK_OF_WEEK_YEAR_METHOD = "getWeekOfWeekyear";
|
||||||
|
static final String GETWEEK_YEAR_METHOD = "getWeekyear";
|
||||||
|
static final String GETYEAR_METHOD = "getYear";
|
||||||
|
static final String GETYEAR_OF_CENTURY_METHOD = "getYearOfCentury";
|
||||||
|
static final String GETYEAR_OF_ERA_METHOD = "getYearOfEra";
|
||||||
|
|
||||||
|
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
|
||||||
|
switch (variable) {
|
||||||
|
case CENTURY_OF_ERA_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getCenturyOfEra);
|
||||||
|
case DAY_OF_MONTH_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getDayOfMonth);
|
||||||
|
case DAY_OF_WEEK_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getDayOfWeek);
|
||||||
|
case DAY_OF_YEAR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getDayOfYear);
|
||||||
|
case ERA_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getEra);
|
||||||
|
case HOUR_OF_DAY_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getHourOfDay);
|
||||||
|
case MILLIS_OF_DAY_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getMillisOfDay);
|
||||||
|
case MILLIS_OF_SECOND_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getMillisOfSecond);
|
||||||
|
case MINUTE_OF_DAY_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getMinuteOfDay);
|
||||||
|
case MINUTE_OF_HOUR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getMinuteOfHour);
|
||||||
|
case MONTH_OF_YEAR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getMonthOfYear);
|
||||||
|
case SECOND_OF_DAY_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getSecondOfDay);
|
||||||
|
case SECOND_OF_MINUTE_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getSecondOfMinute);
|
||||||
|
case WEEK_OF_WEEK_YEAR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getWeekOfWeekyear);
|
||||||
|
case WEEK_YEAR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getWeekyear);
|
||||||
|
case YEAR_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getYear);
|
||||||
|
case YEAR_OF_CENTURY_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getYearOfCentury);
|
||||||
|
case YEAR_OF_ERA_VARIABLE:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getYearOfEra);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Member variable [" + variable +
|
||||||
|
"] does not exist for date object on field [" + fieldName + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
||||||
|
switch (method) {
|
||||||
|
case GETCENTURY_OF_ERA_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getCenturyOfEra);
|
||||||
|
case GETDAY_OF_MONTH_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getDayOfMonth);
|
||||||
|
case GETDAY_OF_WEEK_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getDayOfWeek);
|
||||||
|
case GETDAY_OF_YEAR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getDayOfYear);
|
||||||
|
case GETERA_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getEra);
|
||||||
|
case GETHOUR_OF_DAY_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getHourOfDay);
|
||||||
|
case GETMILLIS_OF_DAY_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getMillisOfDay);
|
||||||
|
case GETMILLIS_OF_SECOND_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getMillisOfSecond);
|
||||||
|
case GETMINUTE_OF_DAY_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getMinuteOfDay);
|
||||||
|
case GETMINUTE_OF_HOUR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getMinuteOfHour);
|
||||||
|
case GETMONTH_OF_YEAR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getMonthOfYear);
|
||||||
|
case GETSECOND_OF_DAY_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getSecondOfDay);
|
||||||
|
case GETSECOND_OF_MINUTE_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getSecondOfMinute);
|
||||||
|
case GETWEEK_OF_WEEK_YEAR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getWeekOfWeekyear);
|
||||||
|
case GETWEEK_YEAR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getWeekyear);
|
||||||
|
case GETYEAR_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getYear);
|
||||||
|
case GETYEAR_OF_CENTURY_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getYearOfCentury);
|
||||||
|
case GETYEAR_OF_ERA_METHOD:
|
||||||
|
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getYearOfEra);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Member method [" + method +
|
||||||
|
"] does not exist for date object on field [" + fieldName + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.script.expression;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
|
import org.apache.lucene.queries.function.FunctionValues;
|
||||||
|
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
|
||||||
|
import org.elasticsearch.index.fielddata.AtomicNumericFieldData;
|
||||||
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
|
import org.elasticsearch.index.fielddata.NumericDoubleValues;
|
||||||
|
import org.elasticsearch.search.MultiValueMode;
|
||||||
|
import org.joda.time.DateTimeZone;
|
||||||
|
import org.joda.time.MutableDateTime;
|
||||||
|
import org.joda.time.ReadableDateTime;
|
||||||
|
|
||||||
|
/** Extracts a portion of a date field with joda time */
|
||||||
|
class DateObjectValueSource extends FieldDataValueSource {
|
||||||
|
|
||||||
|
final String methodName;
|
||||||
|
final ToIntFunction<ReadableDateTime> function;
|
||||||
|
|
||||||
|
DateObjectValueSource(IndexFieldData<?> indexFieldData, MultiValueMode multiValueMode,
|
||||||
|
String methodName, ToIntFunction<ReadableDateTime> function) {
|
||||||
|
super(indexFieldData, multiValueMode);
|
||||||
|
|
||||||
|
Objects.requireNonNull(methodName);
|
||||||
|
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
|
||||||
|
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
|
||||||
|
AtomicNumericFieldData leafData = (AtomicNumericFieldData) fieldData.load(leaf);
|
||||||
|
MutableDateTime joda = new MutableDateTime(0, DateTimeZone.UTC);
|
||||||
|
NumericDoubleValues docValues = multiValueMode.select(leafData.getDoubleValues(), 0d);
|
||||||
|
return new DoubleDocValues(this) {
|
||||||
|
@Override
|
||||||
|
public double doubleVal(int docId) {
|
||||||
|
long millis = (long)docValues.get(docId);
|
||||||
|
joda.setMillis(millis);
|
||||||
|
return function.applyAsInt(joda);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return methodName + ": field(" + fieldData.getFieldName() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
DateObjectValueSource that = (DateObjectValueSource) o;
|
||||||
|
return methodName.equals(that.methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + methodName.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,7 @@ import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -148,6 +149,7 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
||||||
String fieldname = null;
|
String fieldname = null;
|
||||||
String methodname = null;
|
String methodname = null;
|
||||||
String variablename = "value"; // .value is the default for doc['field'], its optional.
|
String variablename = "value"; // .value is the default for doc['field'], its optional.
|
||||||
|
boolean dateAccessor = false; // true if the variable is of type doc['field'].date.xxx
|
||||||
VariableContext[] parts = VariableContext.parse(variable);
|
VariableContext[] parts = VariableContext.parse(variable);
|
||||||
if (parts[0].text.equals("doc") == false) {
|
if (parts[0].text.equals("doc") == false) {
|
||||||
throw new ParseException("Unknown variable [" + parts[0].text + "]", 0);
|
throw new ParseException("Unknown variable [" + parts[0].text + "]", 0);
|
||||||
|
@ -167,7 +169,19 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parts.length > 3) {
|
if (parts.length > 3) {
|
||||||
throw new IllegalArgumentException("Variable [" + variable + "] does not follow an allowed format of either doc['field'] or doc['field'].method()");
|
// access to the .date "object" within the field
|
||||||
|
if (parts.length == 4 && ("date".equals(parts[2].text) || "getDate".equals(parts[2].text))) {
|
||||||
|
if (parts[3].type == VariableContext.Type.METHOD) {
|
||||||
|
methodname = parts[3].text;
|
||||||
|
dateAccessor = true;
|
||||||
|
} else if (parts[3].type == VariableContext.Type.MEMBER) {
|
||||||
|
variablename = parts[3].text;
|
||||||
|
dateAccessor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dateAccessor) {
|
||||||
|
throw new IllegalArgumentException("Variable [" + variable + "] does not follow an allowed format of either doc['field'] or doc['field'].method()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedFieldType fieldType = mapper.fullName(fieldname);
|
MappedFieldType fieldType = mapper.fullName(fieldname);
|
||||||
|
@ -191,11 +205,20 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
|
||||||
}
|
}
|
||||||
} else if (fieldType instanceof LegacyDateFieldMapper.DateFieldType ||
|
} else if (fieldType instanceof LegacyDateFieldMapper.DateFieldType ||
|
||||||
fieldType instanceof DateFieldMapper.DateFieldType) {
|
fieldType instanceof DateFieldMapper.DateFieldType) {
|
||||||
// date
|
if (dateAccessor) {
|
||||||
if (methodname == null) {
|
// date object
|
||||||
valueSource = DateField.getVariable(fieldData, fieldname, variablename);
|
if (methodname == null) {
|
||||||
|
valueSource = DateObject.getVariable(fieldData, fieldname, variablename);
|
||||||
|
} else {
|
||||||
|
valueSource = DateObject.getMethod(fieldData, fieldname, methodname);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
valueSource = DateField.getMethod(fieldData, fieldname, methodname);
|
// date field itself
|
||||||
|
if (methodname == null) {
|
||||||
|
valueSource = DateField.getVariable(fieldData, fieldname, variablename);
|
||||||
|
} else {
|
||||||
|
valueSource = DateField.getMethod(fieldData, fieldname, methodname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (fieldData instanceof IndexNumericFieldData) {
|
} else if (fieldData instanceof IndexNumericFieldData) {
|
||||||
// number
|
// number
|
||||||
|
|
|
@ -34,6 +34,11 @@ final class GeoField {
|
||||||
static final String LAT_VARIABLE = "lat";
|
static final String LAT_VARIABLE = "lat";
|
||||||
static final String LON_VARIABLE = "lon";
|
static final String LON_VARIABLE = "lon";
|
||||||
|
|
||||||
|
// supported methods
|
||||||
|
static final String ISEMPTY_METHOD = "isEmpty";
|
||||||
|
static final String GETLAT_METHOD = "getLat";
|
||||||
|
static final String GETLON_METHOD = "getLon";
|
||||||
|
|
||||||
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
|
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
|
||||||
switch (variable) {
|
switch (variable) {
|
||||||
case EMPTY_VARIABLE:
|
case EMPTY_VARIABLE:
|
||||||
|
@ -48,6 +53,15 @@ final class GeoField {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
||||||
throw new IllegalArgumentException("Member method [" + method + "] does not exist for geo field [" + fieldName + "].");
|
switch (method) {
|
||||||
|
case ISEMPTY_METHOD:
|
||||||
|
return new GeoEmptyValueSource(fieldData);
|
||||||
|
case GETLAT_METHOD:
|
||||||
|
return new GeoLatitudeValueSource(fieldData);
|
||||||
|
case GETLON_METHOD:
|
||||||
|
return new GeoLongitudeValueSource(fieldData);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Member method [" + method + "] does not exist for geo field [" + fieldName + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,12 @@ final class NumericField {
|
||||||
// supported variables
|
// supported variables
|
||||||
static final String VALUE_VARIABLE = "value";
|
static final String VALUE_VARIABLE = "value";
|
||||||
static final String EMPTY_VARIABLE = "empty";
|
static final String EMPTY_VARIABLE = "empty";
|
||||||
|
static final String LENGTH_VARIABLE = "length";
|
||||||
|
|
||||||
// supported methods
|
// supported methods
|
||||||
|
static final String GETVALUE_METHOD = "getValue";
|
||||||
|
static final String ISEMPTY_METHOD = "isEmpty";
|
||||||
|
static final String SIZE_METHOD = "size";
|
||||||
static final String MINIMUM_METHOD = "min";
|
static final String MINIMUM_METHOD = "min";
|
||||||
static final String MAXIMUM_METHOD = "max";
|
static final String MAXIMUM_METHOD = "max";
|
||||||
static final String AVERAGE_METHOD = "avg";
|
static final String AVERAGE_METHOD = "avg";
|
||||||
|
@ -48,6 +52,8 @@ final class NumericField {
|
||||||
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
case EMPTY_VARIABLE:
|
case EMPTY_VARIABLE:
|
||||||
return new EmptyMemberValueSource(fieldData);
|
return new EmptyMemberValueSource(fieldData);
|
||||||
|
case LENGTH_VARIABLE:
|
||||||
|
return new CountMethodValueSource(fieldData);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Member variable [" + variable + "] does not exist for " +
|
throw new IllegalArgumentException("Member variable [" + variable + "] does not exist for " +
|
||||||
"numeric field [" + fieldName + "].");
|
"numeric field [" + fieldName + "].");
|
||||||
|
@ -56,6 +62,12 @@ final class NumericField {
|
||||||
|
|
||||||
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
|
case GETVALUE_METHOD:
|
||||||
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
|
case ISEMPTY_METHOD:
|
||||||
|
return new EmptyMemberValueSource(fieldData);
|
||||||
|
case SIZE_METHOD:
|
||||||
|
return new CountMethodValueSource(fieldData);
|
||||||
case MINIMUM_METHOD:
|
case MINIMUM_METHOD:
|
||||||
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
|
||||||
case MAXIMUM_METHOD:
|
case MAXIMUM_METHOD:
|
||||||
|
|
|
@ -170,6 +170,34 @@ public class MoreExpressionTests extends ESIntegTestCase {
|
||||||
assertEquals(1983.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
assertEquals(1983.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDateObjectMethods() throws Exception {
|
||||||
|
ElasticsearchAssertions.assertAcked(prepareCreate("test").addMapping("doc", "date0", "type=date", "date1", "type=date"));
|
||||||
|
ensureGreen("test");
|
||||||
|
indexRandom(true,
|
||||||
|
client().prepareIndex("test", "doc", "1").setSource("date0", "2015-04-28T04:02:07Z", "date1", "1985-09-01T23:11:01Z"),
|
||||||
|
client().prepareIndex("test", "doc", "2").setSource("date0", "2013-12-25T11:56:45Z", "date1", "1983-10-13T23:15:00Z"));
|
||||||
|
SearchResponse rsp = buildRequest("doc['date0'].date.secondOfMinute - doc['date0'].date.minuteOfHour").get();
|
||||||
|
assertEquals(2, rsp.getHits().getTotalHits());
|
||||||
|
SearchHits hits = rsp.getHits();
|
||||||
|
assertEquals(5.0, hits.getAt(0).field("foo").getValue(), 0.0D);
|
||||||
|
assertEquals(-11.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
||||||
|
rsp = buildRequest("doc['date0'].date.getHourOfDay() + doc['date1'].date.dayOfMonth").get();
|
||||||
|
assertEquals(2, rsp.getHits().getTotalHits());
|
||||||
|
hits = rsp.getHits();
|
||||||
|
assertEquals(5.0, hits.getAt(0).field("foo").getValue(), 0.0D);
|
||||||
|
assertEquals(24.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
||||||
|
rsp = buildRequest("doc['date1'].date.monthOfYear + 1").get();
|
||||||
|
assertEquals(2, rsp.getHits().getTotalHits());
|
||||||
|
hits = rsp.getHits();
|
||||||
|
assertEquals(10.0, hits.getAt(0).field("foo").getValue(), 0.0D);
|
||||||
|
assertEquals(11.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
||||||
|
rsp = buildRequest("doc['date1'].date.year").get();
|
||||||
|
assertEquals(2, rsp.getHits().getTotalHits());
|
||||||
|
hits = rsp.getHits();
|
||||||
|
assertEquals(1985.0, hits.getAt(0).field("foo").getValue(), 0.0D);
|
||||||
|
assertEquals(1983.0, hits.getAt(1).field("foo").getValue(), 0.0D);
|
||||||
|
}
|
||||||
|
|
||||||
public void testMultiValueMethods() throws Exception {
|
public void testMultiValueMethods() throws Exception {
|
||||||
ElasticsearchAssertions.assertAcked(prepareCreate("test").addMapping("doc", "double0", "type=double", "double1", "type=double", "double2", "type=double"));
|
ElasticsearchAssertions.assertAcked(prepareCreate("test").addMapping("doc", "double0", "type=double", "double1", "type=double", "double2", "type=double"));
|
||||||
ensureGreen("test");
|
ensureGreen("test");
|
||||||
|
|
|
@ -50,7 +50,8 @@ public final class Definition {
|
||||||
"java.time.zone.txt",
|
"java.time.zone.txt",
|
||||||
"java.util.txt",
|
"java.util.txt",
|
||||||
"java.util.function.txt",
|
"java.util.function.txt",
|
||||||
"java.util.stream.txt"));
|
"java.util.stream.txt",
|
||||||
|
"joda.time.txt"));
|
||||||
|
|
||||||
private static final Definition INSTANCE = new Definition();
|
private static final Definition INSTANCE = new Definition();
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ public final class Variables {
|
||||||
// Method variables.
|
// Method variables.
|
||||||
|
|
||||||
// This reference. Internal use only.
|
// This reference. Internal use only.
|
||||||
addVariable("[" + Reserved.THIS + "]", Definition.getType("Executable"), Reserved.THIS, true, true);
|
addVariable("[" + Reserved.THIS + "]", Definition.getType("Object"), Reserved.THIS, true, true);
|
||||||
|
|
||||||
// Input map of variables passed to the script.
|
// Input map of variables passed to the script.
|
||||||
addVariable("[" + Reserved.PARAMS + "]", Definition.getType("Map"), Reserved.PARAMS, true, true);
|
addVariable("[" + Reserved.PARAMS + "]", Definition.getType("Map"), Reserved.PARAMS, true, true);
|
||||||
|
|
|
@ -643,9 +643,11 @@ class GregorianCalendar -> java.util.GregorianCalendar extends Calendar,Comparab
|
||||||
GregorianCalendar <init>(int,int,int,int,int,int)
|
GregorianCalendar <init>(int,int,int,int,int,int)
|
||||||
GregorianCalendar <init>(TimeZone)
|
GregorianCalendar <init>(TimeZone)
|
||||||
GregorianCalendar <init>(TimeZone,Locale)
|
GregorianCalendar <init>(TimeZone,Locale)
|
||||||
|
GregorianCalendar from(ZonedDateTime)
|
||||||
Date getGregorianChange()
|
Date getGregorianChange()
|
||||||
boolean isLeapYear(int)
|
boolean isLeapYear(int)
|
||||||
void setGregorianChange(Date)
|
void setGregorianChange(Date)
|
||||||
|
ZonedDateTime toZonedDateTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
class HashMap -> java.util.HashMap extends AbstractMap,Map,Object {
|
class HashMap -> java.util.HashMap extends AbstractMap,Map,Object {
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
#
|
||||||
|
# Licensed to Elasticsearch under one or more contributor
|
||||||
|
# license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright
|
||||||
|
# ownership. Elasticsearch licenses this file to you under
|
||||||
|
# the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Painless definition file. This defines the hierarchy of classes,
|
||||||
|
# what methods and fields they have, etc.
|
||||||
|
#
|
||||||
|
|
||||||
|
# NOTE: this just minimal whitelisting of joda time, just to provide
|
||||||
|
# convenient access via the scripting API. classes are fully qualified to avoid
|
||||||
|
# any confusion with java.time
|
||||||
|
|
||||||
|
class org.joda.time.ReadableInstant -> org.joda.time.ReadableInstant extends Comparable {
|
||||||
|
boolean equals(Object)
|
||||||
|
long getMillis()
|
||||||
|
int hashCode()
|
||||||
|
boolean isAfter(org.joda.time.ReadableInstant)
|
||||||
|
boolean isBefore(org.joda.time.ReadableInstant)
|
||||||
|
boolean isEqual(org.joda.time.ReadableInstant)
|
||||||
|
String toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
class org.joda.time.ReadableDateTime -> org.joda.time.ReadableDateTime extends org.joda.time.ReadableInstant,Comparable {
|
||||||
|
int getCenturyOfEra()
|
||||||
|
int getDayOfMonth()
|
||||||
|
int getDayOfWeek()
|
||||||
|
int getDayOfYear()
|
||||||
|
int getEra()
|
||||||
|
int getHourOfDay()
|
||||||
|
int getMillisOfDay()
|
||||||
|
int getMillisOfSecond()
|
||||||
|
int getMinuteOfDay()
|
||||||
|
int getMinuteOfHour()
|
||||||
|
int getMonthOfYear()
|
||||||
|
int getSecondOfDay()
|
||||||
|
int getSecondOfMinute()
|
||||||
|
int getWeekOfWeekyear()
|
||||||
|
int getWeekyear()
|
||||||
|
int getYear()
|
||||||
|
int getYearOfCentury()
|
||||||
|
int getYearOfEra()
|
||||||
|
String toString(String)
|
||||||
|
String toString(String,Locale)
|
||||||
|
}
|
|
@ -59,28 +59,29 @@ class def -> java.lang.Object {
|
||||||
|
|
||||||
#### ES Scripting API
|
#### ES Scripting API
|
||||||
|
|
||||||
class GeoPoint -> org.elasticsearch.common.geo.GeoPoint extends Object {
|
class org.elasticsearch.common.geo.GeoPoint -> org.elasticsearch.common.geo.GeoPoint extends Object {
|
||||||
double getLat()
|
double getLat()
|
||||||
double getLon()
|
double getLon()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Strings -> org.elasticsearch.index.fielddata.ScriptDocValues$Strings extends List,Collection,Iterable,Object {
|
class org.elasticsearch.index.fielddata.ScriptDocValues.Strings -> org.elasticsearch.index.fielddata.ScriptDocValues$Strings extends List,Collection,Iterable,Object {
|
||||||
String getValue()
|
String getValue()
|
||||||
List getValues()
|
List getValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Longs -> org.elasticsearch.index.fielddata.ScriptDocValues$Longs extends List,Collection,Iterable,Object {
|
class org.elasticsearch.index.fielddata.ScriptDocValues.Longs -> org.elasticsearch.index.fielddata.ScriptDocValues$Longs extends List,Collection,Iterable,Object {
|
||||||
long getValue()
|
long getValue()
|
||||||
List getValues()
|
List getValues()
|
||||||
|
org.joda.time.ReadableDateTime getDate()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Doubles -> org.elasticsearch.index.fielddata.ScriptDocValues$Doubles extends List,Collection,Iterable,Object {
|
class org.elasticsearch.index.fielddata.ScriptDocValues.Doubles -> org.elasticsearch.index.fielddata.ScriptDocValues$Doubles extends List,Collection,Iterable,Object {
|
||||||
double getValue()
|
double getValue()
|
||||||
List getValues()
|
List getValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeoPoints -> org.elasticsearch.index.fielddata.ScriptDocValues$GeoPoints extends List,Collection,Iterable,Object {
|
class org.elasticsearch.index.fielddata.ScriptDocValues.GeoPoints -> org.elasticsearch.index.fielddata.ScriptDocValues$GeoPoints extends List,Collection,Iterable,Object {
|
||||||
GeoPoint getValue()
|
org.elasticsearch.common.geo.GeoPoint getValue()
|
||||||
List getValues()
|
List getValues()
|
||||||
double getLat()
|
double getLat()
|
||||||
double getLon()
|
double getLon()
|
||||||
|
@ -111,9 +112,9 @@ class GeoPoints -> org.elasticsearch.index.fielddata.ScriptDocValues$GeoPoints e
|
||||||
|
|
||||||
# for testing.
|
# for testing.
|
||||||
# currently FeatureTest exposes overloaded constructor, field load store, and overloaded static methods
|
# currently FeatureTest exposes overloaded constructor, field load store, and overloaded static methods
|
||||||
class FeatureTest -> org.elasticsearch.painless.FeatureTest extends Object {
|
class org.elasticsearch.painless.FeatureTest -> org.elasticsearch.painless.FeatureTest extends Object {
|
||||||
FeatureTest <init>()
|
org.elasticsearch.painless.FeatureTest <init>()
|
||||||
FeatureTest <init>(int,int)
|
org.elasticsearch.painless.FeatureTest <init>(int,int)
|
||||||
int getX()
|
int getX()
|
||||||
int getY()
|
int getY()
|
||||||
void setX(int)
|
void setX(int)
|
||||||
|
@ -121,7 +122,3 @@ class FeatureTest -> org.elasticsearch.painless.FeatureTest extends Object {
|
||||||
boolean overloadedStatic()
|
boolean overloadedStatic()
|
||||||
boolean overloadedStatic(boolean)
|
boolean overloadedStatic(boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
# currently needed internally
|
|
||||||
class Executable -> org.elasticsearch.painless.Executable {
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,12 +41,14 @@ public class OverloadTests extends ScriptTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConstructor() {
|
public void testConstructor() {
|
||||||
assertEquals(true, exec("FeatureTest f = new FeatureTest(); return f.x == 0 && f.y == 0;"));
|
assertEquals(true, exec("org.elasticsearch.painless.FeatureTest f = new org.elasticsearch.painless.FeatureTest();" +
|
||||||
assertEquals(true, exec("FeatureTest f = new FeatureTest(1, 2); return f.x == 1 && f.y == 2;"));
|
"return f.x == 0 && f.y == 0;"));
|
||||||
|
assertEquals(true, exec("org.elasticsearch.painless.FeatureTest f = new org.elasticsearch.painless.FeatureTest(1, 2);" +
|
||||||
|
"return f.x == 1 && f.y == 2;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStatic() {
|
public void testStatic() {
|
||||||
assertEquals(true, exec("return FeatureTest.overloadedStatic();"));
|
assertEquals(true, exec("return org.elasticsearch.painless.FeatureTest.overloadedStatic();"));
|
||||||
assertEquals(false, exec("return FeatureTest.overloadedStatic(false);"));
|
assertEquals(false, exec("return org.elasticsearch.painless.FeatureTest.overloadedStatic(false);"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue