org.elasticsearch.client.graph.GraphExploreRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch-rest-high-level-client Show documentation
Show all versions of elasticsearch-rest-high-level-client Show documentation
Elasticsearch subproject :client:rest-high-level
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.client.graph;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Validatable;
import org.elasticsearch.client.ValidationException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.bucket.sampler.SamplerAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.SignificantTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregator;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* Holds the criteria required to guide the exploration of connected terms which
* can be returned as a graph.
*/
public class GraphExploreRequest implements IndicesRequest.Replaceable, ToXContentObject, Validatable {
public static final String NO_HOPS_ERROR_MESSAGE = "Graph explore request must have at least one hop";
public static final String NO_VERTICES_ERROR_MESSAGE = "Graph explore hop must have at least one VertexRequest";
private String[] indices = Strings.EMPTY_ARRAY;
private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, false, true, false);
private String[] types = Strings.EMPTY_ARRAY;
private String routing;
private TimeValue timeout;
private int sampleSize = SamplerAggregationBuilder.DEFAULT_SHARD_SAMPLE_SIZE;
private String sampleDiversityField;
private int maxDocsPerDiversityValue;
private boolean useSignificance = true;
private boolean returnDetailedInfo;
private List hops = new ArrayList<>();
public GraphExploreRequest() {}
/**
* Constructs a new graph request to run against the provided indices. No
* indices means it will run against all indices.
*/
public GraphExploreRequest(String... indices) {
this.indices = indices;
}
@Override
public Optional validate() {
ValidationException validationException = new ValidationException();
if (hops.size() == 0) {
validationException.addValidationError(NO_HOPS_ERROR_MESSAGE);
}
for (Hop hop : hops) {
hop.validate(validationException);
}
return validationException.validationErrors().isEmpty() ? Optional.empty() : Optional.of(validationException);
}
@Override
public String[] indices() {
return this.indices;
}
@Override
public GraphExploreRequest indices(String... indices) {
this.indices = indices;
return this;
}
@Override
public IndicesOptions indicesOptions() {
return indicesOptions;
}
public GraphExploreRequest indicesOptions(IndicesOptions indicesOptions) {
if (indicesOptions == null) {
throw new IllegalArgumentException("IndicesOptions must not be null");
}
this.indicesOptions = indicesOptions;
return this;
}
/**
* The document types to execute the explore against. Defaults to be executed against
* all types.
*
* @deprecated Types are in the process of being removed. Instead of using a type, prefer to
* filter on a field on the document.
*/
@Deprecated
public String[] types() {
return this.types;
}
/**
* The document types to execute the explore request against. Defaults to be executed against
* all types.
*
* @deprecated Types are in the process of being removed. Instead of using a type, prefer to
* filter on a field on the document.
*/
@Deprecated
public GraphExploreRequest types(String... types) {
this.types = types;
return this;
}
public String routing() {
return this.routing;
}
public GraphExploreRequest routing(String routing) {
this.routing = routing;
return this;
}
public GraphExploreRequest routing(String... routings) {
this.routing = Strings.arrayToCommaDelimitedString(routings);
return this;
}
public TimeValue timeout() {
return timeout;
}
/**
* Graph exploration can be set to timeout after the given period. Search
* operations involved in each hop are limited to the remaining time
* available but can still overrun due to the nature of their "best efforts"
* timeout support. When a timeout occurs partial results are returned.
*
* @param timeout
* a {@link TimeValue} object which determines the maximum length
* of time to spend exploring
*/
public GraphExploreRequest timeout(TimeValue timeout) {
if (timeout == null) {
throw new IllegalArgumentException("timeout must not be null");
}
this.timeout = timeout;
return this;
}
public GraphExploreRequest timeout(String timeout) {
timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".timeout"));
return this;
}
@Override
public String toString() {
return "graph explore [" + Arrays.toString(indices) + "][" + Arrays.toString(types) + "]";
}
/**
* The number of top-matching documents that are considered during each hop
* (default is {@link SamplerAggregationBuilder#DEFAULT_SHARD_SAMPLE_SIZE}
* Very small values (less than 50) may not provide sufficient
* weight-of-evidence to identify significant connections between terms.
*
* Very large values (many thousands) are not recommended with loosely
* defined queries (fuzzy queries or those with many OR clauses). This is
* because any useful signals in the best documents are diluted with
* irrelevant noise from low-quality matches. Performance is also typically
* better with smaller samples as there are less look-ups required for
* background frequencies of terms found in the documents
*
*
* @param maxNumberOfDocsPerHop
* shard-level sample size in documents
*/
public void sampleSize(int maxNumberOfDocsPerHop) {
sampleSize = maxNumberOfDocsPerHop;
}
public int sampleSize() {
return sampleSize;
}
/**
* Optional choice of single-value field on which to diversify sampled
* search results
*/
public void sampleDiversityField(String name) {
sampleDiversityField = name;
}
public String sampleDiversityField() {
return sampleDiversityField;
}
/**
* Optional number of permitted docs with same value in sampled search
* results. Must also declare which field using sampleDiversityField
*/
public void maxDocsPerDiversityValue(int maxDocs) {
this.maxDocsPerDiversityValue = maxDocs;
}
public int maxDocsPerDiversityValue() {
return maxDocsPerDiversityValue;
}
/**
* Controls the choice of algorithm used to select interesting terms. The
* default value is true which means terms are selected based on
* significance (see the {@link SignificantTerms} aggregation) rather than
* popularity (using the {@link TermsAggregator}).
*
* @param value
* true if the significant_terms algorithm should be used.
*/
public void useSignificance(boolean value) {
this.useSignificance = value;
}
public boolean useSignificance() {
return useSignificance;
}
/**
* Return detailed information about vertex frequencies as part of JSON
* results - defaults to false
*
* @param value
* true if detailed information is required in JSON responses
*/
public void returnDetailedInfo(boolean value) {
this.returnDetailedInfo = value;
}
public boolean returnDetailedInfo() {
return returnDetailedInfo;
}
/**
* Add a stage in the graph exploration. Each hop represents a stage of
* querying elasticsearch to identify terms which can then be connnected to
* other terms in a subsequent hop.
*
* @param guidingQuery
* optional choice of query which influences which documents are
* considered in this stage
* @return a {@link Hop} object that holds settings for a stage in the graph
* exploration
*/
public Hop createNextHop(QueryBuilder guidingQuery) {
Hop parent = null;
if (hops.size() > 0) {
parent = hops.get(hops.size() - 1);
}
Hop newHop = new Hop(parent);
newHop.guidingQuery = guidingQuery;
hops.add(newHop);
return newHop;
}
public int getHopNumbers() {
return hops.size();
}
public Hop getHop(int hopNumber) {
return hops.get(hopNumber);
}
public static class TermBoost {
String term;
float boost;
public TermBoost(String term, float boost) {
super();
this.term = term;
if (boost <= 0) {
throw new IllegalArgumentException("Boosts must be a positive non-zero number");
}
this.boost = boost;
}
TermBoost() {}
public String getTerm() {
return term;
}
public float getBoost() {
return boost;
}
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.startObject("controls");
{
if (sampleSize != SamplerAggregationBuilder.DEFAULT_SHARD_SAMPLE_SIZE) {
builder.field("sample_size", sampleSize);
}
if (sampleDiversityField != null) {
builder.startObject("sample_diversity");
builder.field("field", sampleDiversityField);
builder.field("max_docs_per_value", maxDocsPerDiversityValue);
builder.endObject();
}
builder.field("use_significance", useSignificance);
if (returnDetailedInfo) {
builder.field("return_detailed_stats", returnDetailedInfo);
}
}
builder.endObject();
for (Hop hop : hops) {
if (hop.parentHop != null) {
builder.startObject("connections");
}
hop.toXContent(builder, params);
}
for (Hop hop : hops) {
if (hop.parentHop != null) {
builder.endObject();
}
}
builder.endObject();
return builder;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy