org.elasticsearch.search.suggest.SuggestBuilder Maven / Gradle / Ivy
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.search.suggest;
import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.suggest.context.CategoryContextMapping;
import org.elasticsearch.search.suggest.context.ContextMapping.ContextQuery;
import org.elasticsearch.search.suggest.context.GeolocationContextMapping;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Defines how to perform suggesting. This builders allows a number of global options to be specified and
* an arbitrary number of {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder} instances.
*
* Suggesting works by suggesting terms that appear in the suggest text that are similar compared to the terms in
* provided text. These spelling suggestions are based on several options described in this class.
*/
public class SuggestBuilder extends ToXContentToBytes {
private final String name;
private String globalText;
private final List> suggestions = new ArrayList<>();
public SuggestBuilder() {
this.name = null;
}
public SuggestBuilder(String name) {
this.name = name;
}
/**
* Sets the text to provide suggestions for. The suggest text is a required option that needs
* to be set either via this setter or via the {@link org.elasticsearch.search.suggest.SuggestBuilder.SuggestionBuilder#setText(String)} method.
*
* The suggest text gets analyzed by the suggest analyzer or the suggest field search analyzer.
* For each analyzed token, suggested terms are suggested if possible.
*/
public SuggestBuilder setText(String globalText) {
this.globalText = globalText;
return this;
}
/**
* Adds an {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder} instance under a user defined name.
* The order in which the Suggestions
are added, is the same as in the response.
*/
public SuggestBuilder addSuggestion(SuggestionBuilder> suggestion) {
suggestions.add(suggestion);
return this;
}
/**
* Returns all suggestions with the defined names.
*/
public List> getSuggestion() {
return suggestions;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if(name == null) {
builder.startObject();
} else {
builder.startObject(name);
}
if (globalText != null) {
builder.field("text", globalText);
}
for (SuggestionBuilder> suggestion : suggestions) {
builder = suggestion.toXContent(builder, params);
}
builder.endObject();
return builder;
}
public static abstract class SuggestionBuilder extends ToXContentToBytes {
private String name;
private String suggester;
private String text;
private String field;
private String analyzer;
private Integer size;
private Integer shardSize;
private List contextQueries = new ArrayList<>();
public SuggestionBuilder(String name, String suggester) {
this.name = name;
this.suggester = suggester;
}
@SuppressWarnings("unchecked")
private T addContextQuery(ContextQuery ctx) {
this.contextQueries.add(ctx);
return (T) this;
}
/**
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
* @param lat Latitude of the location
* @param lon Longitude of the Location
* @return this
*/
public T addGeoLocation(String name, double lat, double lon, int ... precisions) {
return addContextQuery(GeolocationContextMapping.query(name, lat, lon, precisions));
}
/**
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
* @param lat Latitude of the location
* @param lon Longitude of the Location
* @param precisions precisions as string var-args
* @return this
*/
public T addGeoLocationWithPrecision(String name, double lat, double lon, String ... precisions) {
return addContextQuery(GeolocationContextMapping.query(name, lat, lon, precisions));
}
/**
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
* @param geohash Geohash of the location
* @return this
*/
public T addGeoLocation(String name, String geohash) {
return addContextQuery(GeolocationContextMapping.query(name, geohash));
}
/**
* Setup a Category for suggestions. See {@link CategoryContextMapping}.
* @param categories name of the category
* @return this
*/
public T addCategory(String name, CharSequence...categories) {
return addContextQuery(CategoryContextMapping.query(name, categories));
}
/**
* Setup a Category for suggestions. See {@link CategoryContextMapping}.
* @param categories name of the category
* @return this
*/
public T addCategory(String name, Iterable extends CharSequence> categories) {
return addContextQuery(CategoryContextMapping.query(name, categories));
}
/**
* Setup a Context Field for suggestions. See {@link CategoryContextMapping}.
* @param fieldvalues name of the category
* @return this
*/
public T addContextField(String name, CharSequence...fieldvalues) {
return addContextQuery(CategoryContextMapping.query(name, fieldvalues));
}
/**
* Setup a Context Field for suggestions. See {@link CategoryContextMapping}.
* @param fieldvalues name of the category
* @return this
*/
public T addContextField(String name, Iterable extends CharSequence> fieldvalues) {
return addContextQuery(CategoryContextMapping.query(name, fieldvalues));
}
/**
* Same as in {@link SuggestBuilder#setText(String)}, but in the suggestion scope.
*/
@SuppressWarnings("unchecked")
public T text(String text) {
this.text = text;
return (T) this;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(name);
if (text != null) {
builder.field("text", text);
}
builder.startObject(suggester);
if (analyzer != null) {
builder.field("analyzer", analyzer);
}
if (field != null) {
builder.field("field", field);
}
if (size != null) {
builder.field("size", size);
}
if (shardSize != null) {
builder.field("shard_size", shardSize);
}
if (!contextQueries.isEmpty()) {
builder.startObject("context");
for (ContextQuery query : contextQueries) {
query.toXContent(builder, params);
}
builder.endObject();
}
builder = innerToXContent(builder, params);
builder.endObject();
builder.endObject();
return builder;
}
protected abstract XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException;
/**
* Sets from what field to fetch the candidate suggestions from. This is an
* required option and needs to be set via this setter or
* {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder#field(String)}
* method
*/
@SuppressWarnings("unchecked")
public T field(String field) {
this.field = field;
return (T)this;
}
/**
* Sets the analyzer to analyse to suggest text with. Defaults to the search
* analyzer of the suggest field.
*/
@SuppressWarnings("unchecked")
public T analyzer(String analyzer) {
this.analyzer = analyzer;
return (T)this;
}
/**
* Sets the maximum suggestions to be returned per suggest text term.
*/
@SuppressWarnings("unchecked")
public T size(int size) {
if (size <= 0) {
throw new IllegalArgumentException("Size must be positive");
}
this.size = size;
return (T)this;
}
/**
* Sets the maximum number of suggested term to be retrieved from each
* individual shard. During the reduce phase the only the top N suggestions
* are returned based on the size
option. Defaults to the
* size
option.
*
* Setting this to a value higher than the `size` can be useful in order to
* get a more accurate document frequency for suggested terms. Due to the
* fact that terms are partitioned amongst shards, the shard level document
* frequencies of suggestions may not be precise. Increasing this will make
* these document frequencies more precise.
*/
@SuppressWarnings("unchecked")
public T shardSize(Integer shardSize) {
this.shardSize = shardSize;
return (T)this;
}
}
}