org.codelibs.elasticsearch.common.lucene.search.Queries 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.common.lucene.search;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.codelibs.elasticsearch.common.Nullable;
import java.util.List;
import java.util.regex.Pattern;
/**
*
*/
public class Queries {
public static Query newMatchAllQuery() {
return new MatchAllDocsQuery();
}
/** Return a query that matches no document. */
public static Query newMatchNoDocsQuery(String reason) {
return new MatchNoDocsQuery(reason);
}
public static Query newNestedFilter() {
throw new UnsupportedOperationException("querybuilders does not support this operation.");
}
public static Query newNonNestedFilter() {
return not(newNestedFilter());
}
public static BooleanQuery filtered(@Nullable Query query, @Nullable Query filter) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
if (query != null) {
builder.add(new BooleanClause(query, Occur.MUST));
}
if (filter != null) {
builder.add(new BooleanClause(filter, Occur.FILTER));
}
return builder.build();
}
/** Return a query that matches all documents but those that match the given query. */
public static Query not(Query q) {
return new BooleanQuery.Builder()
.add(new MatchAllDocsQuery(), Occur.MUST)
.add(q, Occur.MUST_NOT)
.build();
}
private static boolean isNegativeQuery(Query q) {
if (!(q instanceof BooleanQuery)) {
return false;
}
List clauses = ((BooleanQuery) q).clauses();
if (clauses.isEmpty()) {
return false;
}
for (BooleanClause clause : clauses) {
if (!clause.isProhibited()) {
return false;
}
}
return true;
}
public static Query fixNegativeQueryIfNeeded(Query q) {
if (isNegativeQuery(q)) {
BooleanQuery bq = (BooleanQuery) q;
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.setDisableCoord(bq.isCoordDisabled());
for (BooleanClause clause : bq) {
builder.add(clause);
}
builder.add(newMatchAllQuery(), BooleanClause.Occur.MUST);
return builder.build();
}
return q;
}
public static boolean isConstantMatchAllQuery(Query query) {
if (query instanceof ConstantScoreQuery) {
return isConstantMatchAllQuery(((ConstantScoreQuery) query).getQuery());
} else if (query instanceof MatchAllDocsQuery) {
return true;
}
return false;
}
public static Query applyMinimumShouldMatch(BooleanQuery query, @Nullable String minimumShouldMatch) {
if (minimumShouldMatch == null) {
return query;
}
int optionalClauses = 0;
for (BooleanClause c : query.clauses()) {
if (c.getOccur() == BooleanClause.Occur.SHOULD) {
optionalClauses++;
}
}
int msm = calculateMinShouldMatch(optionalClauses, minimumShouldMatch);
if (0 < msm) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.setDisableCoord(query.isCoordDisabled());
for (BooleanClause clause : query) {
builder.add(clause);
}
builder.setMinimumNumberShouldMatch(msm);
return builder.build();
} else {
return query;
}
}
private static Pattern spaceAroundLessThanPattern = Pattern.compile("(\\s+<\\s*)|(\\s*<\\s+)");
private static Pattern spacePattern = Pattern.compile(" ");
private static Pattern lessThanPattern = Pattern.compile("<");
public static int calculateMinShouldMatch(int optionalClauseCount, String spec) {
int result = optionalClauseCount;
spec = spec.trim();
if (-1 < spec.indexOf("<")) {
/* we have conditional spec(s) */
spec = spaceAroundLessThanPattern.matcher(spec).replaceAll("<");
for (String s : spacePattern.split(spec)) {
String[] parts = lessThanPattern.split(s, 0);
int upperBound = Integer.parseInt(parts[0]);
if (optionalClauseCount <= upperBound) {
return result;
} else {
result = calculateMinShouldMatch
(optionalClauseCount, parts[1]);
}
}
return result;
}
/* otherwise, simple expression */
if (-1 < spec.indexOf('%')) {
/* percentage - assume the % was the last char. If not, let Integer.parseInt fail. */
spec = spec.substring(0, spec.length() - 1);
int percent = Integer.parseInt(spec);
float calc = (result * percent) * (1 / 100f);
result = calc < 0 ? result + (int) calc : (int) calc;
} else {
int calc = Integer.parseInt(spec);
result = calc < 0 ? result + calc : calc;
}
return result < 0 ? 0 : result;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy