com.emc.query.bool.BoolQueryBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.emc.query.bool.BoolQueryBuilder.java

Source

/*
 * 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 com.emc.query.bool;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;

import com.emc.query.QueryBuilder;
import com.emc.queryBuilder.AbstractQueryBuilder;
import com.emc.queryBuilder.XContentBuilder;

/**
 * A Query that matches documents matching boolean combinations of other queries.
 * @param <T>
 */
public class BoolQueryBuilder extends AbstractQueryBuilder {

    public static final String NAME = "bool";

    public static final boolean ADJUST_PURE_NEGATIVE_DEFAULT = true;

    public static final boolean DISABLE_COORD_DEFAULT = false;

    static final BoolQueryBuilder PROTOTYPE = new BoolQueryBuilder();

    private final List<QueryBuilder<?>> mustClauses = new ArrayList<>();

    private final List<QueryBuilder<?>> mustNotClauses = new ArrayList<>();

    private final List<QueryBuilder<?>> filterClauses = new ArrayList<>();

    private final List<QueryBuilder<?>> shouldClauses = new ArrayList<>();

    private boolean disableCoord = DISABLE_COORD_DEFAULT;

    private boolean adjustPureNegative = ADJUST_PURE_NEGATIVE_DEFAULT;

    private String minimumShouldMatch;

    /**
     * Adds a query that <b>must</b> appear in the matching documents and will
     * contribute to scoring. No <tt>null</tt> value allowed.
     */
    public BoolQueryBuilder must(QueryBuilder<?> queryBuilder) {
        if (queryBuilder == null) {
            throw new IllegalArgumentException("inner bool query clause cannot be null");
        }
        mustClauses.add(queryBuilder);
        return this;
    }

    /**
     * Gets the queries that <b>must</b> appear in the matching documents.
     */
    public List<QueryBuilder<?>> must() {
        return this.mustClauses;
    }

    /**
     * Adds a query that <b>must</b> appear in the matching documents but will
     * not contribute to scoring. No <tt>null</tt> value allowed.
     */
    public BoolQueryBuilder filter(QueryBuilder<?> queryBuilder) {
        if (queryBuilder == null) {
            throw new IllegalArgumentException("inner bool query clause cannot be null");
        }
        filterClauses.add(queryBuilder);
        return this;
    }

    /**
     * Gets the queries that <b>must</b> appear in the matching documents but don't contribute to scoring
     */
    public List<QueryBuilder<?>> filter() {
        return this.filterClauses;
    }

    /**
     * Adds a query that <b>must not</b> appear in the matching documents.
     * No <tt>null</tt> value allowed.
     */
    public BoolQueryBuilder mustNot(QueryBuilder<?> queryBuilder) {
        if (queryBuilder == null) {
            throw new IllegalArgumentException("inner bool query clause cannot be null");
        }
        mustNotClauses.add(queryBuilder);
        return this;
    }

    /**
     * Gets the queries that <b>must not</b> appear in the matching documents.
     */
    public List<QueryBuilder<?>> mustNot() {
        return this.mustNotClauses;
    }

    /**
     * Adds a clause that <i>should</i> be matched by the returned documents. For a boolean query with no
     * <tt>MUST</tt> clauses one or more <code>SHOULD</code> clauses must match a document
     * for the BooleanQuery to match. No <tt>null</tt> value allowed.
     *
     * @see #minimumNumberShouldMatch(int)
     */
    public BoolQueryBuilder should(QueryBuilder<?> queryBuilder) {
        if (queryBuilder == null) {
            throw new IllegalArgumentException("inner bool query clause cannot be null");
        }
        shouldClauses.add(queryBuilder);
        return this;
    }

    /**
     * Gets the list of clauses that <b>should</b> be matched by the returned documents.
     *
     * @see #should(QueryBuilder)
     *  @see #minimumNumberShouldMatch(int)
     */
    public List<QueryBuilder<?>> should() {
        return this.shouldClauses;
    }

    /**
     * Disables <tt>Similarity#coord(int,int)</tt> in scoring. Defaults to <tt>false</tt>.
     */
    public BoolQueryBuilder disableCoord(boolean disableCoord) {
        this.disableCoord = disableCoord;
        return this;
    }

    /**
     * @return whether the <tt>Similarity#coord(int,int)</tt> in scoring are disabled. Defaults to <tt>false</tt>.
     */
    public boolean disableCoord() {
        return this.disableCoord;
    }

    /**
     * Specifies a minimum number of the optional (should) boolean clauses which must be satisfied.
     * <p>
     * By default no optional clauses are necessary for a match
     * (unless there are no required clauses).  If this method is used,
     * then the specified number of clauses is required.
     * <p>
     * Use of this method is totally independent of specifying that
     * any specific clauses are required (or prohibited).  This number will
     * only be compared against the number of matching optional clauses.
     *
     * @param minimumNumberShouldMatch the number of optional clauses that must match
     */
    public BoolQueryBuilder minimumNumberShouldMatch(int minimumNumberShouldMatch) {
        this.minimumShouldMatch = Integer.toString(minimumNumberShouldMatch);
        return this;
    }

    /**
     * Specifies a minimum number of the optional (should) boolean clauses which must be satisfied.
     * @see BoolQueryBuilder#minimumNumberShouldMatch(int)
     */
    public BoolQueryBuilder minimumNumberShouldMatch(String minimumNumberShouldMatch) {
        this.minimumShouldMatch = minimumNumberShouldMatch;
        return this;
    }

    /**
     * @return the string representation of the minimumShouldMatch settings for this query
     */
    public String minimumShouldMatch() {
        return this.minimumShouldMatch;
    }

    /**
     * Sets the minimum should match using the special syntax (for example, supporting percentage).
     */
    public BoolQueryBuilder minimumShouldMatch(String minimumShouldMatch) {
        this.minimumShouldMatch = minimumShouldMatch;
        return this;
    }

    /**
     * Returns <code>true</code> iff this query builder has at least one should, must, must not or filter clause.
     * Otherwise <code>false</code>.
     */
    public boolean hasClauses() {
        return !(mustClauses.isEmpty() && shouldClauses.isEmpty() && mustNotClauses.isEmpty()
                && filterClauses.isEmpty());
    }

    /**
     * If a boolean query contains only negative ("must not") clauses should the
     * BooleanQuery be enhanced with a {@link MatchAllDocsQuery} in order to act
     * as a pure exclude. The default is <code>true</code>.
     */
    public BoolQueryBuilder adjustPureNegative(boolean adjustPureNegative) {
        this.adjustPureNegative = adjustPureNegative;
        return this;
    }

    /**
     * @return the setting for the adjust_pure_negative setting in this query
     */
    public boolean adjustPureNegative() {
        return this.adjustPureNegative;
    }

    @Override
    public void doXContent(XContentBuilder builder, String[] params) throws IOException {
        builder.startObject(NAME);
        doXArrayContent(BoolQueryParser.MUST, mustClauses, builder, params);
        doXArrayContent(BoolQueryParser.FILTER, filterClauses, builder, params);
        doXArrayContent(BoolQueryParser.MUST_NOT, mustNotClauses, builder, params);
        doXArrayContent(BoolQueryParser.SHOULD, shouldClauses, builder, params);
        builder.field(BoolQueryParser.DISABLE_COORD_FIELD.getPreferredName(), disableCoord);
        builder.field(BoolQueryParser.ADJUST_PURE_NEGATIVE.getPreferredName(), adjustPureNegative);
        if (minimumShouldMatch != null) {
            builder.field(BoolQueryParser.MINIMUM_SHOULD_MATCH.getPreferredName(), minimumShouldMatch);
        }
        printBoostAndQueryName(builder);
        builder.endObject();
    }

    private void printBoostAndQueryName(XContentBuilder builder) {
        // TODO Auto-generated method stub

    }

    private static void doXArrayContent(String field, List<QueryBuilder<?>> clauses, XContentBuilder builder,
            String[] params) throws IOException {
        if (clauses.isEmpty()) {
            return;
        }
        builder.startArray(field);
        for (QueryBuilder<?> clause : clauses) {
            clause.toXContent(builder, params);
        }
        builder.endArray();
    }

    @Override
    public String getWriteableName() {
        return NAME;
    }

    //    @Override
    //    protected Query doToQuery(QueryShardContext context) throws IOException {
    //        BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
    //        booleanQueryBuilder.setDisableCoord(disableCoord);
    //        addBooleanClauses(context, booleanQueryBuilder, mustClauses, BooleanClause.Occur.MUST);
    //        addBooleanClauses(context, booleanQueryBuilder, mustNotClauses, BooleanClause.Occur.MUST_NOT);
    //        addBooleanClauses(context, booleanQueryBuilder, shouldClauses, BooleanClause.Occur.SHOULD);
    //        addBooleanClauses(context, booleanQueryBuilder, filterClauses, BooleanClause.Occur.FILTER);
    //        BooleanQuery booleanQuery = booleanQueryBuilder.build();
    //        if (booleanQuery.clauses().isEmpty()) {
    //            return new MatchAllDocsQuery();
    //        }
    //
    //        final String minimumShouldMatch;
    //        if (context.isFilter() && this.minimumShouldMatch == null && shouldClauses.size() > 0) {
    //            minimumShouldMatch = "1";
    //        } else {
    //            minimumShouldMatch = this.minimumShouldMatch;
    //        }
    //        Query query = Queries.applyMinimumShouldMatch(booleanQuery, minimumShouldMatch);
    //        return adjustPureNegative ? fixNegativeQueryIfNeeded(query) : query;
    //    }

    protected Query doToQuery() {
        BooleanQuery query = new BooleanQuery();

        return null;
    }

    @Override
    public String toXQuery() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void toXContent(XContentBuilder builder, String[] params) {
        // TODO Auto-generated method stub

    }

    //    private static void addBooleanClauses(QueryShardContext context, BooleanQuery.Builder booleanQueryBuilder, List<QueryBuilder<?>> clauses, Occur occurs) throws IOException {
    //        for (QueryBuilder<?> query : clauses) {
    //            Query luceneQuery = null;
    //            switch (occurs) {
    //                case MUST:
    //                case SHOULD:
    //                    luceneQuery = query.toQuery(context);
    //                    break;
    //                case FILTER:
    //                case MUST_NOT:
    //                    luceneQuery = query.toFilter(context);
    //                    break;
    //            }
    //            if (luceneQuery != null) {
    //                booleanQueryBuilder.add(new BooleanClause(luceneQuery, occurs));
    //            }
    //        }
    //    }
    //
    //    @Override
    //    protected int doHashCode() {
    //        return Objects.hash(adjustPureNegative, disableCoord,
    //                minimumShouldMatch, mustClauses, shouldClauses, mustNotClauses, filterClauses);
    //    }
    //
    //    @Override
    //    protected boolean doEquals(BoolQueryBuilder other) {
    //        return Objects.equals(adjustPureNegative, other.adjustPureNegative) &&
    //                Objects.equals(disableCoord, other.disableCoord) &&
    //                Objects.equals(minimumShouldMatch, other.minimumShouldMatch) &&
    //                Objects.equals(mustClauses, other.mustClauses) &&
    //                Objects.equals(shouldClauses, other.shouldClauses) &&
    //                Objects.equals(mustNotClauses, other.mustNotClauses) &&
    //                Objects.equals(filterClauses, other.filterClauses);
    //    }
    //
    //    @Override
    //    protected BoolQueryBuilder doReadFrom(StreamInput in) throws IOException {
    //        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    //        List<QueryBuilder<?>> queryBuilders = readQueries(in);
    //        boolQueryBuilder.mustClauses.addAll(queryBuilders);
    //        queryBuilders = readQueries(in);
    //        boolQueryBuilder.mustNotClauses.addAll(queryBuilders);
    //        queryBuilders = readQueries(in);
    //        boolQueryBuilder.shouldClauses.addAll(queryBuilders);
    //        queryBuilders = readQueries(in);
    //        boolQueryBuilder.filterClauses.addAll(queryBuilders);
    //        boolQueryBuilder.adjustPureNegative = in.readBoolean();
    //        boolQueryBuilder.disableCoord = in.readBoolean();
    //        boolQueryBuilder.minimumShouldMatch = in.readOptionalString();
    //        return boolQueryBuilder;
    //
    //    }
    //
    //    @Override
    //    protected void doWriteTo(StreamOutput out) throws IOException {
    //        writeQueries(out, mustClauses);
    //        writeQueries(out, mustNotClauses);
    //        writeQueries(out, shouldClauses);
    //        writeQueries(out, filterClauses);
    //        out.writeBoolean(adjustPureNegative);
    //        out.writeBoolean(disableCoord);
    //        out.writeOptionalString(minimumShouldMatch);
    //    }
    //
    //    @Override
    //    protected QueryBuilder<?> doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
    //        BoolQueryBuilder newBuilder = new BoolQueryBuilder();
    //        boolean changed = false;
    //        final int clauses = mustClauses.size() + mustNotClauses.size() + filterClauses.size() + shouldClauses.size();
    //        if (clauses == 0) {
    //            return new MatchAllQueryBuilder().boost(boost()).queryName(queryName());
    //        }
    //        changed |= rewriteClauses(queryRewriteContext, mustClauses, newBuilder::must);
    //        changed |= rewriteClauses(queryRewriteContext, mustNotClauses, newBuilder::mustNot);
    //        changed |= rewriteClauses(queryRewriteContext, filterClauses, newBuilder::filter);
    //        changed |= rewriteClauses(queryRewriteContext, shouldClauses, newBuilder::should);
    //
    //        if (changed) {
    //            newBuilder.adjustPureNegative = adjustPureNegative;
    //            newBuilder.disableCoord = disableCoord;
    //            newBuilder.minimumShouldMatch = minimumShouldMatch;
    //            newBuilder.boost(boost());
    //            newBuilder.queryName(queryName());
    //            return newBuilder;
    //        }
    //        return this;
    //    }
    //
    //    private static boolean rewriteClauses(QueryRewriteContext queryRewriteContext, List<QueryBuilder<?>> builders, Consumer<QueryBuilder<?>> consumer) throws IOException {
    //        boolean changed = false;
    //        for (QueryBuilder builder : builders) {
    //            QueryBuilder result = builder.rewrite(queryRewriteContext);
    //            if (result != builder) {
    //                changed = true;
    //            }
    //            consumer.accept(result);
    //        }
    //        return changed;
    //    }
    //
    //   @Override
    //   public String toXQuery() {
    //      // TODO Auto-generated method stub
    //      return null;
    //   }
    //
    //   @Override
    //   public void toXContent(XContentBuilder builder, String[] params) {
    //      // TODO Auto-generated method stub
    //      
    //   }
}