org.codelibs.elasticsearch.index.query.SpanNotQueryBuilder 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.codelibs.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanNotQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.codelibs.elasticsearch.common.ParseField;
import org.codelibs.elasticsearch.common.ParsingException;
import org.codelibs.elasticsearch.common.io.stream.StreamInput;
import org.codelibs.elasticsearch.common.io.stream.StreamOutput;
import org.codelibs.elasticsearch.common.xcontent.XContentBuilder;
import org.codelibs.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
public class SpanNotQueryBuilder extends AbstractQueryBuilder implements SpanQueryBuilder {
public static final String NAME = "span_not";
/** the default pre parameter size */
public static final int DEFAULT_PRE = 0;
/** the default post parameter size */
public static final int DEFAULT_POST = 0;
private static final ParseField POST_FIELD = new ParseField("post");
private static final ParseField PRE_FIELD = new ParseField("pre");
private static final ParseField DIST_FIELD = new ParseField("dist");
private static final ParseField EXCLUDE_FIELD = new ParseField("exclude");
private static final ParseField INCLUDE_FIELD = new ParseField("include");
private final SpanQueryBuilder include;
private final SpanQueryBuilder exclude;
private int pre = DEFAULT_PRE;
private int post = DEFAULT_POST;
/**
* Construct a span query matching spans from include
which
* have no overlap with spans from exclude
.
* @param include the span query whose matches are filtered
* @param exclude the span query whose matches must not overlap
*/
public SpanNotQueryBuilder(SpanQueryBuilder include, SpanQueryBuilder exclude) {
if (include == null) {
throw new IllegalArgumentException("inner clause [include] cannot be null.");
}
if (exclude == null) {
throw new IllegalArgumentException("inner clause [exclude] cannot be null.");
}
this.include = include;
this.exclude = exclude;
}
/**
* Read from a stream.
*/
public SpanNotQueryBuilder(StreamInput in) throws IOException {
super(in);
include = (SpanQueryBuilder) in.readNamedWriteable(QueryBuilder.class);
exclude = (SpanQueryBuilder) in.readNamedWriteable(QueryBuilder.class);
pre = in.readVInt();
post = in.readVInt();
}
@Override
protected void doWriteTo(StreamOutput out) throws IOException {
out.writeNamedWriteable(include);
out.writeNamedWriteable(exclude);
out.writeVInt(pre);
out.writeVInt(post);
}
/**
* @return the span query whose matches are filtered
*/
public SpanQueryBuilder includeQuery() {
return this.include;
}
/**
* @return the span query whose matches must not overlap
*/
public SpanQueryBuilder excludeQuery() {
return this.exclude;
}
/**
* @param dist the amount of tokens from within the include span can’t have overlap with the exclude span.
* Equivalent to setting both pre and post parameter.
*/
public SpanNotQueryBuilder dist(int dist) {
pre(dist);
post(dist);
return this;
}
/**
* @param pre the amount of tokens before the include span that can’t have overlap with the exclude span. Values
* smaller than 0 will be ignored and 0 used instead.
*/
public SpanNotQueryBuilder pre(int pre) {
this.pre = (pre >= 0) ? pre : 0;
return this;
}
/**
* @return the amount of tokens before the include span that can’t have overlap with the exclude span.
* @see SpanNotQueryBuilder#pre(int)
*/
public Integer pre() {
return this.pre;
}
/**
* @param post the amount of tokens after the include span that can’t have overlap with the exclude span.
*/
public SpanNotQueryBuilder post(int post) {
this.post = (post >= 0) ? post : 0;
return this;
}
/**
* @return the amount of tokens after the include span that can’t have overlap with the exclude span.
* @see SpanNotQueryBuilder#post(int)
*/
public Integer post() {
return this.post;
}
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
builder.field(INCLUDE_FIELD.getPreferredName());
include.toXContent(builder, params);
builder.field(EXCLUDE_FIELD.getPreferredName());
exclude.toXContent(builder, params);
builder.field(PRE_FIELD.getPreferredName(), pre);
builder.field(POST_FIELD.getPreferredName(), post);
printBoostAndQueryName(builder);
builder.endObject();
}
public static Optional fromXContent(QueryParseContext parseContext) throws IOException {
XContentParser parser = parseContext.parser();
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
SpanQueryBuilder include = null;
SpanQueryBuilder exclude = null;
Integer dist = null;
Integer pre = null;
Integer post = null;
String queryName = null;
String currentFieldName = null;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if (INCLUDE_FIELD.match(currentFieldName)) {
Optional query = parseContext.parseInnerQueryBuilder();
if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) {
throw new ParsingException(parser.getTokenLocation(), "spanNot [include] must be of type span query");
}
include = (SpanQueryBuilder) query.get();
} else if (EXCLUDE_FIELD.match(currentFieldName)) {
Optional query = parseContext.parseInnerQueryBuilder();
if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) {
throw new ParsingException(parser.getTokenLocation(), "spanNot [exclude] must be of type span query");
}
exclude = (SpanQueryBuilder) query.get();
} else {
throw new ParsingException(parser.getTokenLocation(), "[span_not] query does not support [" + currentFieldName + "]");
}
} else {
if (DIST_FIELD.match(currentFieldName)) {
dist = parser.intValue();
} else if (PRE_FIELD.match(currentFieldName)) {
pre = parser.intValue();
} else if (POST_FIELD.match(currentFieldName)) {
post = parser.intValue();
} else if (AbstractQueryBuilder.BOOST_FIELD.match(currentFieldName)) {
boost = parser.floatValue();
} else if (AbstractQueryBuilder.NAME_FIELD.match(currentFieldName)) {
queryName = parser.text();
} else {
throw new ParsingException(parser.getTokenLocation(), "[span_not] query does not support [" + currentFieldName + "]");
}
}
}
if (include == null) {
throw new ParsingException(parser.getTokenLocation(), "spanNot must have [include] span query clause");
}
if (exclude == null) {
throw new ParsingException(parser.getTokenLocation(), "spanNot must have [exclude] span query clause");
}
if (dist != null && (pre != null || post != null)) {
throw new ParsingException(parser.getTokenLocation(), "spanNot can either use [dist] or [pre] & [post] (or none)");
}
SpanNotQueryBuilder spanNotQuery = new SpanNotQueryBuilder(include, exclude);
if (dist != null) {
spanNotQuery.dist(dist);
}
if (pre != null) {
spanNotQuery.pre(pre);
}
if (post != null) {
spanNotQuery.post(post);
}
spanNotQuery.boost(boost);
spanNotQuery.queryName(queryName);
return Optional.of(spanNotQuery);
}
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
Query includeQuery = this.include.toQuery(context);
assert includeQuery instanceof SpanQuery;
Query excludeQuery = this.exclude.toQuery(context);
assert excludeQuery instanceof SpanQuery;
return new SpanNotQuery((SpanQuery) includeQuery, (SpanQuery) excludeQuery, pre, post);
}
@Override
protected int doHashCode() {
return Objects.hash(include, exclude, pre, post);
}
@Override
protected boolean doEquals(SpanNotQueryBuilder other) {
return Objects.equals(include, other.include) &&
Objects.equals(exclude, other.exclude) &&
(pre == other.pre) &&
(post == other.post);
}
@Override
public String getWriteableName() {
return NAME;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy