Skip to content

Commit

Permalink
Refactors SpanTermQueryBuilder.
Browse files Browse the repository at this point in the history
This attempts to do to SpanTermQueryBuilder what has already been changed for TermQueryBuilder.

The commit tries to avoid code duplication where possible by pulling what is the same for both QueryBuilders and tests into separate classes.

Relates to elastic#10217
  • Loading branch information
Isabel Drost-Fromm committed May 6, 2015
1 parent a83490f commit e20b6b4
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 281 deletions.
221 changes: 221 additions & 0 deletions src/main/java/org/elasticsearch/index/query/BaseTermQueryBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* 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.index.query;

import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Objects;

public abstract class BaseTermQueryBuilder extends BaseQueryBuilder implements Streamable {

/** Name of field to match against. */
protected String fieldName;

/** Value to find matches for. */
protected Object value;

/** Query boost. */
protected float boost = 1.0f;

/** Name of the query. */
protected String queryName;

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, String value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, int value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, long value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, float value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, double value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, boolean value) {
this(fieldName, (Object) value);
}

/**
* Constructs a new base term query.
*
* @param fieldName The name of the field
* @param value The value of the term
*/
public BaseTermQueryBuilder(String fieldName, Object value) {
this.fieldName = fieldName;
if (value instanceof String) {
this.value = BytesRefs.toBytesRef(value);
} else {
this.value = value;
}
}

BaseTermQueryBuilder() {
// for serialization only
}

/** Returns the field name used in this query @see org.apache.lucene.search.spans.SpanTermQuery#getField() */
public String fieldName() {
return this.fieldName;
}

/** Returns the value used in this query @see org.apache.lucene.index.Term#text() */
public Object value() {
return this.value;
}

/** Returns the query name for the query. */
public String queryName() {
return this.queryName;
}
/** Returns the boost for this query. @see org.apache.lucene.search.Query#setBoost() */
public float boost() {
return this.boost;
}

@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
Object valueToWrite = value;
if (value instanceof BytesRef) {
valueToWrite = ((BytesRef) value).utf8ToString();
}

if (boost == 1.0f && queryName == null) {
builder.field(fieldName, valueToWrite);
} else {
builder.startObject(fieldName);
builder.field("value", valueToWrite);
if (boost != 1.0f) {
builder.field("boost", boost);
}
if (queryName != null) {
builder.field("_name", queryName);
}
builder.endObject();
}
builder.endObject();
}

/** Returns a {@link QueryValidationException} if fieldName is null or empty, or if value is null. */
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (fieldName == null || fieldName.isEmpty()) {
validationException = QueryValidationException.addValidationError("field name cannot be null or empty.", validationException);
}
if (value == null) {
validationException = QueryValidationException.addValidationError("value cannot be null.", validationException);
}
return validationException;
}


@Override
public int hashCode() {
/*
* Added class name to the hashcode so a {@link SpanTermQueryBuilder} and a {@link TermQueryBuilder} aren't considered the same
* if they have the same parameters set.
*/
return Objects.hash(getClass(), fieldName, value, boost, queryName);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
BaseTermQueryBuilder other = (BaseTermQueryBuilder) obj;
return Objects.equals(fieldName, other.fieldName) &&
Objects.equals(value, other.value) &&
Objects.equals(boost, other.boost) &&
Objects.equals(queryName, other.queryName);
}

/** Read the given parameters. */
@Override
public void readFrom(StreamInput in) throws IOException {
fieldName = in.readString();
value = in.readGenericValue();
boost = in.readFloat();
queryName = in.readOptionalString();
}

/** Writes the given parameters. */
public void writeTo(StreamOutput out) throws IOException {
out.writeString(fieldName);
out.writeGenericValue(value);
out.writeFloat(boost);
out.writeOptionalString(queryName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,83 +19,95 @@

package org.elasticsearch.index.query;

import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.MapperService;

import java.io.IOException;

/**
*
* A Span Query that matches documents containing a term.
* @see SpanTermQuery
*/
public class SpanTermQueryBuilder extends BaseQueryBuilder implements SpanQueryBuilder, BoostableQueryBuilder<SpanTermQueryBuilder> {

private final String name;

private final Object value;

private float boost = -1;

private String queryName;

public class SpanTermQueryBuilder extends BaseTermQueryBuilder implements SpanQueryBuilder, BoostableQueryBuilder<SpanTermQueryBuilder> {
/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, String value) {
this(name, (Object) value);
super(name, (Object) value);
}

/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, int value) {
this(name, (Object) value);
super(name, (Object) value);
}

/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, long value) {
this(name, (Object) value);
super(name, (Object) value);
}

/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, float value) {
this(name, (Object) value);
super(name, (Object) value);
}

/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, double value) {
this(name, (Object) value);
super(name, (Object) value);
}
/** {@inheritDoc} */
public SpanTermQueryBuilder(String name, Object value) {
super(name, value);
}

private SpanTermQueryBuilder(String name, Object value) {
this.name = name;
this.value = value;
SpanTermQueryBuilder() {
super();
// for testing and serialisation only
}

/** @see org.apache.lucene.search.Query#getBoost() */
@Override
public SpanTermQueryBuilder boost(float boost) {
this.boost = boost;
return this;
}

/**
* Sets the query name for the filter that can be used when searching for matched_filters per hit.
*/

/** Sets the query name for the filter that can be used when searching for matched_filters per hit. */
public SpanTermQueryBuilder queryName(String queryName) {
this.queryName = queryName;
return this;
}

/** {@inheritDoc} */
@Override
public void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(SpanTermQueryParser.NAME);
if (boost == -1 && queryName != null) {
builder.field(name, value);
} else {
builder.startObject(name);
builder.field("value", value);
if (boost != -1) {
builder.field("boost", boost);
}
if (queryName != null) {
builder.field("_name", queryName);
}
builder.endObject();
}
builder.endObject();
super.doXContent(builder, params);
}

@Override
protected String parserName() {
return SpanTermQueryParser.NAME;
}

@Override
public Query toQuery(QueryParseContext context) {
BytesRef valueBytes = null;
MapperService.SmartNameFieldMappers smartNameFieldMappers = context.smartFieldMappers(fieldName);
if (smartNameFieldMappers != null) {
if (smartNameFieldMappers.hasMapper()) {
fieldName = smartNameFieldMappers.mapper().names().indexName();
valueBytes = smartNameFieldMappers.mapper().indexedValueForSearch(value);
}
}
if (valueBytes == null) {
valueBytes = BytesRefs.toBytesRef(this.value);
}

SpanTermQuery query = new SpanTermQuery(new Term(fieldName, valueBytes));
query.setBoost(boost);
if (queryName != null) {
context.addNamedQuery(queryName, query);
}
return query;
}
}
Loading

0 comments on commit e20b6b4

Please sign in to comment.