-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Query refactoring: SpanNotQueryBuilder and Parser #12365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
cbuescher
merged 1 commit into
elastic:feature/query-refactoring
from
cbuescher:feature/query-refactoring-spannot
Jul 22, 2015
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,82 +19,172 @@ | |
|
|
||
| package org.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.elasticsearch.common.io.stream.StreamInput; | ||
| import org.elasticsearch.common.io.stream.StreamOutput; | ||
| import org.elasticsearch.common.xcontent.XContentBuilder; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Objects; | ||
|
|
||
| public class SpanNotQueryBuilder extends AbstractQueryBuilder<SpanNotQueryBuilder> implements SpanQueryBuilder<SpanNotQueryBuilder> { | ||
|
|
||
| public static final String NAME = "span_not"; | ||
|
|
||
| private SpanQueryBuilder include; | ||
| /** 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 SpanQueryBuilder exclude; | ||
| private final SpanQueryBuilder include; | ||
|
|
||
| private Integer dist; | ||
| private final SpanQueryBuilder exclude; | ||
|
|
||
| private Integer pre; | ||
| private int pre = DEFAULT_PRE; | ||
|
|
||
| private Integer post; | ||
| private int post = DEFAULT_POST; | ||
|
|
||
| static final SpanNotQueryBuilder PROTOTYPE = new SpanNotQueryBuilder(); | ||
|
|
||
| public SpanNotQueryBuilder include(SpanQueryBuilder include) { | ||
| this.include = include; | ||
| return this; | ||
| /** | ||
| * Construct a span query matching spans from <code>include</code> which | ||
| * have no overlap with spans from <code>exclude</code>. | ||
| * @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) { | ||
| this.include = Objects.requireNonNull(include); | ||
| this.exclude = Objects.requireNonNull(exclude); | ||
| } | ||
|
|
||
| public SpanNotQueryBuilder exclude(SpanQueryBuilder exclude) { | ||
| this.exclude = exclude; | ||
| return this; | ||
| // only used for prototype | ||
| private SpanNotQueryBuilder() { | ||
| this.include = null; | ||
| this.exclude = null; | ||
| } | ||
|
|
||
| /** | ||
| * @return the span query whose matches are filtered | ||
| */ | ||
| public SpanQueryBuilder include() { | ||
| return this.include; | ||
| } | ||
|
|
||
| /** | ||
| * @return the span query whose matches must not overlap | ||
| */ | ||
| public SpanQueryBuilder exclude() { | ||
| 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) { | ||
| this.dist = 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; | ||
| 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 { | ||
| if (include == null) { | ||
| throw new IllegalArgumentException("Must specify include when using spanNot query"); | ||
| } | ||
| if (exclude == null) { | ||
| throw new IllegalArgumentException("Must specify exclude when using spanNot query"); | ||
| } | ||
|
|
||
| if (dist != null && (pre != null || post != null)) { | ||
| throw new IllegalArgumentException("spanNot can either use [dist] or [pre] & [post] (or none)"); | ||
| } | ||
|
|
||
| builder.startObject(NAME); | ||
| builder.field("include"); | ||
| include.toXContent(builder, params); | ||
| builder.field("exclude"); | ||
| exclude.toXContent(builder, params); | ||
| if (dist != null) { | ||
| builder.field("dist", dist); | ||
| } | ||
| if (pre != null) { | ||
| builder.field("pre", pre); | ||
| } | ||
| if (post != null) { | ||
| builder.field("post", post); | ||
| } | ||
| builder.field("pre", pre); | ||
| builder.field("post", post); | ||
| printBoostAndQueryName(builder); | ||
| builder.endObject(); | ||
| } | ||
|
|
||
| @Override | ||
| protected Query doToQuery(QueryParseContext parseContext) throws IOException { | ||
|
|
||
| Query includeQuery = this.include.toQuery(parseContext); | ||
| assert includeQuery instanceof SpanQuery; | ||
| Query excludeQuery = this.exclude.toQuery(parseContext); | ||
| assert excludeQuery instanceof SpanQuery; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we have problems with LateParsingQuery here too? maybe an if instead of an assert?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, already discussed in #12342 (comment) |
||
|
|
||
| SpanNotQuery query = new SpanNotQuery((SpanQuery) includeQuery, (SpanQuery) excludeQuery, pre, post); | ||
| return query; | ||
| } | ||
|
|
||
| @Override | ||
| public QueryValidationException validate() { | ||
| QueryValidationException validationExceptions = validateInnerQuery(include, null); | ||
| validationExceptions = validateInnerQuery(exclude, validationExceptions); | ||
| return validationExceptions; | ||
| } | ||
|
|
||
| @Override | ||
| protected SpanNotQueryBuilder doReadFrom(StreamInput in) throws IOException { | ||
| SpanQueryBuilder include = in.readNamedWriteable(); | ||
| SpanQueryBuilder exclude = in.readNamedWriteable(); | ||
| SpanNotQueryBuilder queryBuilder = new SpanNotQueryBuilder(include, exclude); | ||
| queryBuilder.pre(in.readVInt()); | ||
| queryBuilder.post(in.readVInt()); | ||
| return queryBuilder; | ||
| } | ||
|
|
||
| @Override | ||
| protected void doWriteTo(StreamOutput out) throws IOException { | ||
| out.writeNamedWriteable(include); | ||
| out.writeNamedWriteable(exclude); | ||
| out.writeVInt(pre); | ||
| out.writeVInt(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 getName() { | ||
| return NAME; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we lost dist here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting dist is equivalent to setting pre/post to the same value, so I removed the internal representation for dist entirely. Only caveat here is that if user sets dist on the builder, query is logged with per/post fields, but since we said doXContent will be used for logging / debugging only after refactoring this is similar to outputting defaults that user hasn't explicitely set, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright, sounds good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should start thinking about testing the parsing phase for things that we never output from doXContent.... :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can start doing this here, only problem is creating the JSON without the builder is kind of messy. But I will add a test for dist parameter for the parser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know what you mean about creating the json, plain strings would work I guess... we have this same problem in other queries (e.g. term query)...something we have to keep in mind for later.