@Override public Mapper parse(ParseContext context) throws IOException { try { Shape shape = context.parseExternalValue(Shape.class); if (shape == null) { ShapeBuilder shapeBuilder = ShapeBuilder.parse(context.parser(), this); if (shapeBuilder == null) { return null; } shape = shapeBuilder.build(); } if (fieldType().pointsOnly() && !(shape instanceof Point)) { throw new MapperParsingException( "[{" + fieldType().names().fullName() + "}] is configured for points only but a " + ((shape instanceof JtsGeometry) ? ((JtsGeometry) shape).getGeom().getGeometryType() : shape.getClass()) + " was found"); } Field[] fields = fieldType().defaultStrategy().createIndexableFields(shape); if (fields == null || fields.length == 0) { return null; } for (Field field : fields) { if (!customBoost()) { field.setBoost(fieldType().boost()); } context.doc().add(field); } } catch (Exception e) { throw new MapperParsingException( "failed to parse [" + fieldType().names().fullName() + "]", e); } return null; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); String fieldName = null; ShapeRelation shapeRelation = ShapeRelation.INTERSECTS; String strategyName = null; ShapeBuilder shape = null; FilterCachingPolicy cache = parseContext.autoFilterCachePolicy(); HashedBytesRef cacheKey = null; String filterName = null; String id = null; String type = null; String index = DEFAULTS.INDEX_NAME; String shapePath = DEFAULTS.SHAPE_FIELD_NAME; XContentParser.Token token; String currentFieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); token = parser.nextToken(); if ("shape".equals(currentFieldName)) { shape = ShapeBuilder.parse(parser); } else if ("relation".equals(currentFieldName)) { shapeRelation = ShapeRelation.getRelationByName(parser.text()); if (shapeRelation == null) { throw new QueryParsingException( parseContext.index(), "Unknown shape operation [" + parser.text() + "]"); } } else if ("strategy".equals(currentFieldName)) { strategyName = parser.text(); } else if ("indexed_shape".equals(currentFieldName) || "indexedShape".equals(currentFieldName)) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token.isValue()) { if ("id".equals(currentFieldName)) { id = parser.text(); } else if ("type".equals(currentFieldName)) { type = parser.text(); } else if ("index".equals(currentFieldName)) { index = parser.text(); } else if ("path".equals(currentFieldName)) { shapePath = parser.text(); } } } if (id == null) { throw new QueryParsingException( parseContext.index(), "ID for indexed shape not provided"); } else if (type == null) { throw new QueryParsingException( parseContext.index(), "Type for indexed shape not provided"); } shape = fetchService.fetch(id, type, index, shapePath); } else { throw new QueryParsingException( parseContext.index(), "[geo_shape] filter does not support [" + currentFieldName + "]"); } } } } else if (token.isValue()) { if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parseContext.parseFilterCachePolicy(); } else if ("_cache_key".equals(currentFieldName)) { cacheKey = new HashedBytesRef(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[geo_shape] filter does not support [" + currentFieldName + "]"); } } } if (shape == null) { throw new QueryParsingException(parseContext.index(), "No Shape defined"); } else if (shapeRelation == null) { throw new QueryParsingException(parseContext.index(), "No Shape Relation defined"); } MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers == null || !smartNameFieldMappers.hasMapper()) { throw new QueryParsingException( parseContext.index(), "Failed to find geo_shape field [" + fieldName + "]"); } FieldMapper fieldMapper = smartNameFieldMappers.mapper(); // TODO: This isn't the nicest way to check this if (!(fieldMapper instanceof GeoShapeFieldMapper)) { throw new QueryParsingException( parseContext.index(), "Field [" + fieldName + "] is not a geo_shape"); } GeoShapeFieldMapper shapeFieldMapper = (GeoShapeFieldMapper) fieldMapper; PrefixTreeStrategy strategy = shapeFieldMapper.defaultStrategy(); if (strategyName != null) { strategy = shapeFieldMapper.resolveStrategy(strategyName); } Filter filter; if (strategy instanceof RecursivePrefixTreeStrategy && shapeRelation == ShapeRelation.DISJOINT) { // this strategy doesn't support disjoint anymore: but it did before, including creating // lucene fieldcache (!) // in this case, execute disjoint as exists && !intersects XBooleanFilter bool = new XBooleanFilter(); Filter exists = ExistsFilterParser.newFilter(parseContext, fieldName, null); Filter intersects = strategy.makeFilter(GeoShapeQueryParser.getArgs(shape, ShapeRelation.INTERSECTS)); bool.add(exists, BooleanClause.Occur.MUST); bool.add(intersects, BooleanClause.Occur.MUST_NOT); filter = bool; } else { filter = strategy.makeFilter(GeoShapeQueryParser.getArgs(shape, shapeRelation)); } if (cache != null) { filter = parseContext.cacheFilter(filter, cacheKey, cache); } if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }