Exemple #1
0
 @Override
 protected XContentBuilder doInternalXContent(XContentBuilder builder, Params params)
     throws IOException {
   if (size >= 0) {
     builder.field("size", size);
   }
   if (shardSize >= 0) {
     builder.field("shard_size", shardSize);
   }
   if (minDocCount >= 0) {
     builder.field("min_doc_count", minDocCount);
   }
   if (valueType != null) {
     builder.field("value_type", valueType.name().toLowerCase(Locale.ROOT));
   }
   if (order != null) {
     builder.field("order");
     order.toXContent(builder, params);
   }
   if (includePattern != null) {
     if (includeFlags == 0) {
       builder.field("include", includePattern);
     } else {
       builder
           .startObject("include")
           .field("pattern", includePattern)
           .field("flags", includeFlags)
           .endObject();
     }
   }
   if (excludePattern != null) {
     if (excludeFlags == 0) {
       builder.field("exclude", excludePattern);
     } else {
       builder
           .startObject("exclude")
           .field("pattern", excludePattern)
           .field("flags", excludeFlags)
           .endObject();
     }
   }
   if (executionHint != null) {
     builder.field("execution_hint", executionHint);
   }
   return builder;
 }
  @Override
  public AggregatorFactory parse(
      String aggregationName, XContentParser parser, SearchContext context) throws IOException {

    String field = null;
    String script = null;
    String scriptLang = null;
    Map<String, Object> scriptParams = null;
    Terms.ValueType valueType = null;
    int requiredSize = 10;
    String orderKey = "_count";
    boolean orderAsc = false;
    String format = null;
    boolean assumeUnique = false;

    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.VALUE_STRING) {
        if ("field".equals(currentFieldName)) {
          field = parser.text();
        } else if ("script".equals(currentFieldName)) {
          script = parser.text();
        } else if ("script_lang".equals(currentFieldName)
            || "scriptLang".equals(currentFieldName)) {
          scriptLang = parser.text();
        } else if ("value_type".equals(currentFieldName) || "valueType".equals(currentFieldName)) {
          valueType = Terms.ValueType.resolveType(parser.text());
        } else if ("format".equals(currentFieldName)) {
          format = parser.text();
        }
      } else if (token == XContentParser.Token.VALUE_BOOLEAN) {
        if ("script_values_unique".equals(currentFieldName)) {
          assumeUnique = parser.booleanValue();
        }
      } else if (token == XContentParser.Token.VALUE_NUMBER) {
        if ("size".equals(currentFieldName)) {
          requiredSize = parser.intValue();
        }
      } else if (token == XContentParser.Token.START_OBJECT) {
        if ("params".equals(currentFieldName)) {
          scriptParams = parser.map();
        } else if ("order".equals(currentFieldName)) {
          while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
            if (token == XContentParser.Token.FIELD_NAME) {
              orderKey = parser.currentName();
            } else if (token == XContentParser.Token.VALUE_STRING) {
              String dir = parser.text();
              orderAsc = "asc".equalsIgnoreCase(dir);
              // TODO: do we want to throw a parse error if the alternative is not "desc"???
            }
          }
        }
      }
    }

    InternalOrder order = resolveOrder(orderKey, orderAsc);
    SearchScript searchScript = null;
    if (script != null) {
      searchScript =
          context.scriptService().search(context.lookup(), scriptLang, script, scriptParams);
    }

    if (field == null) {

      Class<? extends ValuesSource> valueSourceType =
          script == null
              ? ValuesSource.class
              : // unknown, will inherit whatever is in the context
              valueType != null
                  ? valueType.scriptValueType.getValuesSourceType()
                  : // the user explicitly defined a value type
                  BytesValuesSource.class; // defaulting to bytes

      ValuesSourceConfig<?> config = new ValuesSourceConfig(valueSourceType);
      if (valueType != null) {
        config.scriptValueType(valueType.scriptValueType);
      }
      config.script(searchScript);
      if (!assumeUnique) {
        config.ensureUnique(true);
      }
      return new TermsAggregatorFactory(aggregationName, config, order, requiredSize);
    }

    FieldMapper<?> mapper = context.smartNameFieldMapper(field);
    if (mapper == null) {
      ValuesSourceConfig<?> config =
          new ValuesSourceConfig<BytesValuesSource>(BytesValuesSource.class);
      config.unmapped(true);
      return new TermsAggregatorFactory(aggregationName, config, order, requiredSize);
    }
    IndexFieldData<?> indexFieldData = context.fieldData().getForField(mapper);

    ValuesSourceConfig<?> config;

    if (mapper instanceof DateFieldMapper) {
      DateFieldMapper dateMapper = (DateFieldMapper) mapper;
      ValueFormatter formatter =
          format == null
              ? new ValueFormatter.DateTime(dateMapper.dateTimeFormatter())
              : new ValueFormatter.DateTime(format);
      config =
          new ValuesSourceConfig<NumericValuesSource>(NumericValuesSource.class)
              .formatter(formatter)
              .parser(new ValueParser.DateMath(dateMapper.dateMathParser()));

    } else if (mapper instanceof IpFieldMapper) {
      config =
          new ValuesSourceConfig<NumericValuesSource>(NumericValuesSource.class)
              .formatter(ValueFormatter.IPv4)
              .parser(ValueParser.IPv4);

    } else if (indexFieldData instanceof IndexNumericFieldData) {
      config = new ValuesSourceConfig<NumericValuesSource>(NumericValuesSource.class);
      if (format != null) {
        config.formatter(new ValueFormatter.Number.Pattern(format));
      }

    } else {
      config = new ValuesSourceConfig<BytesValuesSource>(BytesValuesSource.class);
      // TODO: it will make sense to set false instead here if the aggregator factory uses
      // ordinals instead of hash tables
      config.needsHashes(true);
    }

    config.script(searchScript);

    config.fieldContext(new FieldContext(field, indexFieldData));

    // We need values to be unique to be able to run terms aggs efficiently
    if (!assumeUnique) {
      config.ensureUnique(true);
    }

    return new TermsAggregatorFactory(aggregationName, config, order, requiredSize);
  }