From efe85f322a073313d35f7261bfbe04baa3235de1 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Sat, 23 Jun 2012 17:25:02 +0200 Subject: [PATCH] better type based inference when using scripts --- .../index/get/ShardGetService.java | 8 ++-- .../mapper/geo/GeoPointDocFieldData.java | 42 +++++++++++++++++++ .../index/query/QueryParseContext.java | 2 +- .../elasticsearch/script/ScriptService.java | 2 +- .../search/internal/SearchContext.java | 3 +- .../search/lookup/DocLookup.java | 14 +++++-- .../search/lookup/FieldsLookup.java | 12 ++++-- .../search/lookup/SearchLookup.java | 7 ++-- 8 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/get/ShardGetService.java b/src/main/java/org/elasticsearch/index/get/ShardGetService.java index a4161863531..861636985b6 100644 --- a/src/main/java/org/elasticsearch/index/get/ShardGetService.java +++ b/src/main/java/org/elasticsearch/index/get/ShardGetService.java @@ -193,7 +193,7 @@ public class ShardGetService extends AbstractIndexShardComponent { Object value = null; if (field.contains("_source.") || field.contains("doc[")) { if (searchLookup == null) { - searchLookup = new SearchLookup(mapperService, indexCache.fieldData()); + searchLookup = new SearchLookup(mapperService, indexCache.fieldData(), new String[]{type}); } SearchScript searchScript = scriptService.search(searchLookup, "mvel", field, null); searchScript.setNextReader(docIdAndVersion.reader); @@ -211,7 +211,7 @@ public class ShardGetService extends AbstractIndexShardComponent { FieldMappers x = docMapper.mappers().smartName(field); if (x == null || !x.mapper().stored()) { if (searchLookup == null) { - searchLookup = new SearchLookup(mapperService, indexCache.fieldData()); + searchLookup = new SearchLookup(mapperService, indexCache.fieldData(), new String[]{type}); searchLookup.setNextReader(docIdAndVersion.reader); searchLookup.setNextDocId(docIdAndVersion.docId); } @@ -271,7 +271,7 @@ public class ShardGetService extends AbstractIndexShardComponent { } else { if (field.contains("_source.")) { if (searchLookup == null) { - searchLookup = new SearchLookup(mapperService, indexCache.fieldData()); + searchLookup = new SearchLookup(mapperService, indexCache.fieldData(), new String[]{type}); } if (sourceAsMap == null) { sourceAsMap = SourceLookup.sourceAsMap(source.source.bytes(), source.source.offset(), source.source.length()); @@ -294,7 +294,7 @@ public class ShardGetService extends AbstractIndexShardComponent { } } else { if (searchLookup == null) { - searchLookup = new SearchLookup(mapperService, indexCache.fieldData()); + searchLookup = new SearchLookup(mapperService, indexCache.fieldData(), new String[]{type}); searchLookup.source().setNextSource(source.source.bytes(), source.source.offset(), source.source.length()); } diff --git a/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointDocFieldData.java b/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointDocFieldData.java index c56c1ddb8ef..f807f666022 100644 --- a/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointDocFieldData.java +++ b/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointDocFieldData.java @@ -43,6 +43,13 @@ public class GeoPointDocFieldData extends DocFieldData { return fieldData.factorDistance(docId, DistanceUnit.MILES, lat, lon); } + public double factorDistanceWithDefault(double lat, double lon, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.factorDistance(docId, DistanceUnit.MILES, lat, lon); + } + public double factorDistance02(double lat, double lon) { return fieldData.factorDistance(docId, DistanceUnit.MILES, lat, lon) + 1; } @@ -55,22 +62,57 @@ public class GeoPointDocFieldData extends DocFieldData { return fieldData.arcDistance(docId, DistanceUnit.MILES, lat, lon); } + public double arcDistanceWithDefault(double lat, double lon, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.arcDistance(docId, DistanceUnit.MILES, lat, lon); + } + public double arcDistanceInKm(double lat, double lon) { return fieldData.arcDistance(docId, DistanceUnit.KILOMETERS, lat, lon); } + public double arcDistanceInKmWithDefault(double lat, double lon, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.arcDistance(docId, DistanceUnit.KILOMETERS, lat, lon); + } + public double distance(double lat, double lon) { return fieldData.distance(docId, DistanceUnit.MILES, lat, lon); } + public double distanceWithDefault(double lat, double lon, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.distance(docId, DistanceUnit.MILES, lat, lon); + } + public double distanceInKm(double lat, double lon) { return fieldData.distance(docId, DistanceUnit.KILOMETERS, lat, lon); } + public double distanceInKmWithDefault(double lat, double lon, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.distance(docId, DistanceUnit.KILOMETERS, lat, lon); + } + public double geohashDistance(String geohash) { return fieldData.distanceGeohash(docId, DistanceUnit.MILES, geohash); } + public double geohashDistanceWithDefault(String geohash, double defaultValue) { + if (!fieldData.hasValue(docId)) { + return defaultValue; + } + return fieldData.distanceGeohash(docId, DistanceUnit.MILES, geohash); + } + public double geohashDistanceInKm(String geohash) { return fieldData.distanceGeohash(docId, DistanceUnit.KILOMETERS, geohash); } diff --git a/src/main/java/org/elasticsearch/index/query/QueryParseContext.java b/src/main/java/org/elasticsearch/index/query/QueryParseContext.java index 309678a2000..18cc8eb584f 100644 --- a/src/main/java/org/elasticsearch/index/query/QueryParseContext.java +++ b/src/main/java/org/elasticsearch/index/query/QueryParseContext.java @@ -290,7 +290,7 @@ public class QueryParseContext { return current.lookup(); } if (lookup == null) { - lookup = new SearchLookup(mapperService(), indexCache().fieldData()); + lookup = new SearchLookup(mapperService(), indexCache().fieldData(), null); } return lookup; } diff --git a/src/main/java/org/elasticsearch/script/ScriptService.java b/src/main/java/org/elasticsearch/script/ScriptService.java index d6f2fd3b3fd..55bd291f08b 100644 --- a/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/src/main/java/org/elasticsearch/script/ScriptService.java @@ -180,7 +180,7 @@ public class ScriptService extends AbstractComponent { } public SearchScript search(MapperService mapperService, FieldDataCache fieldDataCache, String lang, String script, @Nullable Map vars) { - return search(compile(lang, script), new SearchLookup(mapperService, fieldDataCache), vars); + return search(compile(lang, script), new SearchLookup(mapperService, fieldDataCache, null), vars); } public Object execute(CompiledScript compiledScript, Map vars) { diff --git a/src/main/java/org/elasticsearch/search/internal/SearchContext.java b/src/main/java/org/elasticsearch/search/internal/SearchContext.java index ba563034294..d86cdd37e80 100644 --- a/src/main/java/org/elasticsearch/search/internal/SearchContext.java +++ b/src/main/java/org/elasticsearch/search/internal/SearchContext.java @@ -520,8 +520,9 @@ public class SearchContext implements Releasable { } public SearchLookup lookup() { + // TODO: The types should take into account the parsing context in QueryParserContext... if (searchLookup == null) { - searchLookup = new SearchLookup(mapperService(), fieldDataCache()); + searchLookup = new SearchLookup(mapperService(), fieldDataCache(), request.types()); } return searchLookup; } diff --git a/src/main/java/org/elasticsearch/search/lookup/DocLookup.java b/src/main/java/org/elasticsearch/search/lookup/DocLookup.java index 2118f30f219..f4fe9ddb689 100644 --- a/src/main/java/org/elasticsearch/search/lookup/DocLookup.java +++ b/src/main/java/org/elasticsearch/search/lookup/DocLookup.java @@ -24,6 +24,7 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Scorer; import org.elasticsearch.ElasticSearchException; import org.elasticsearch.ElasticSearchIllegalArgumentException; +import org.elasticsearch.common.Nullable; import org.elasticsearch.index.cache.field.data.FieldDataCache; import org.elasticsearch.index.field.data.DocFieldData; import org.elasticsearch.index.field.data.FieldData; @@ -32,6 +33,7 @@ import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Set; @@ -47,15 +49,19 @@ public class DocLookup implements Map { private final FieldDataCache fieldDataCache; + @Nullable + private final String[] types; + private IndexReader reader; private Scorer scorer; private int docId = -1; - DocLookup(MapperService mapperService, FieldDataCache fieldDataCache) { + DocLookup(MapperService mapperService, FieldDataCache fieldDataCache, @Nullable String[] types) { this.mapperService = mapperService; this.fieldDataCache = fieldDataCache; + this.types = types; } public MapperService mapperService() { @@ -105,9 +111,9 @@ public class DocLookup implements Map { String fieldName = key.toString(); FieldData fieldData = localCacheFieldData.get(fieldName); if (fieldData == null) { - FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName); + FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName, types); if (mapper == null) { - throw new ElasticSearchIllegalArgumentException("No field found for [" + fieldName + "]"); + throw new ElasticSearchIllegalArgumentException("No field found for [" + fieldName + "] in mapping with types " + Arrays.toString(types) + ""); } try { fieldData = fieldDataCache.cache(mapper.fieldDataType(), reader, mapper.names().indexName()); @@ -124,7 +130,7 @@ public class DocLookup implements Map { String fieldName = key.toString(); FieldData fieldData = localCacheFieldData.get(fieldName); if (fieldData == null) { - FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName); + FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName, types); if (mapper == null) { return false; } diff --git a/src/main/java/org/elasticsearch/search/lookup/FieldsLookup.java b/src/main/java/org/elasticsearch/search/lookup/FieldsLookup.java index d556c330c3a..d3bd8e2ee7b 100644 --- a/src/main/java/org/elasticsearch/search/lookup/FieldsLookup.java +++ b/src/main/java/org/elasticsearch/search/lookup/FieldsLookup.java @@ -23,11 +23,13 @@ import com.google.common.collect.Maps; import org.apache.lucene.index.IndexReader; import org.elasticsearch.ElasticSearchIllegalArgumentException; import org.elasticsearch.ElasticSearchParseException; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.document.SingleFieldSelector; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Set; @@ -39,6 +41,9 @@ public class FieldsLookup implements Map { private final MapperService mapperService; + @Nullable + private final String[] types; + private IndexReader reader; private int docId = -1; @@ -47,8 +52,9 @@ public class FieldsLookup implements Map { private final SingleFieldSelector fieldSelector = new SingleFieldSelector(); - FieldsLookup(MapperService mapperService) { + FieldsLookup(MapperService mapperService, @Nullable String[] types) { this.mapperService = mapperService; + this.types = types; } public void setNextReader(IndexReader reader) { @@ -137,9 +143,9 @@ public class FieldsLookup implements Map { private FieldLookup loadFieldData(String name) { FieldLookup data = cachedFieldData.get(name); if (data == null) { - FieldMapper mapper = mapperService.smartNameFieldMapper(name); + FieldMapper mapper = mapperService.smartNameFieldMapper(name, types); if (mapper == null) { - throw new ElasticSearchIllegalArgumentException("No field found for [" + name + "]"); + throw new ElasticSearchIllegalArgumentException("No field found for [" + name + "] in mapping with types " + Arrays.toString(types) + ""); } data = new FieldLookup(mapper); cachedFieldData.put(name, data); diff --git a/src/main/java/org/elasticsearch/search/lookup/SearchLookup.java b/src/main/java/org/elasticsearch/search/lookup/SearchLookup.java index 2c07e507f40..c5b3d1a4819 100644 --- a/src/main/java/org/elasticsearch/search/lookup/SearchLookup.java +++ b/src/main/java/org/elasticsearch/search/lookup/SearchLookup.java @@ -22,6 +22,7 @@ package org.elasticsearch.search.lookup; import com.google.common.collect.ImmutableMap; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Scorer; +import org.elasticsearch.common.Nullable; import org.elasticsearch.index.cache.field.data.FieldDataCache; import org.elasticsearch.index.mapper.MapperService; @@ -38,10 +39,10 @@ public class SearchLookup { final ImmutableMap asMap; - public SearchLookup(MapperService mapperService, FieldDataCache fieldDataCache) { - docMap = new DocLookup(mapperService, fieldDataCache); + public SearchLookup(MapperService mapperService, FieldDataCache fieldDataCache, @Nullable String[] types) { + docMap = new DocLookup(mapperService, fieldDataCache, types); sourceLookup = new SourceLookup(); - fieldsLookup = new FieldsLookup(mapperService); + fieldsLookup = new FieldsLookup(mapperService, types); asMap = ImmutableMap.of("doc", docMap, "_doc", docMap, "_source", sourceLookup, "_fields", fieldsLookup); }