Ejemplo n.º 1
0
 @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;
  }