Search in sources :

Example 1 with MCRCondition

use of org.mycore.parsers.bool.MCRCondition in project mycore by MyCoRe-Org.

the class MCRQueryParser method normalizeCondition.

/**
 * Normalizes a parsed query condition. AND/OR conditions that just have one
 * child will be replaced with that child. NOT(NOT(X)) will be normalized to X.
 * (A AND (b AND c)) will be normalized to (A AND B AND C), same for nested ORs.
 * AND/OR/NOT conditions with no child conditions will be removed.
 * Conditions that use the operator "contains" will be splitted into multiple
 * simpler conditions if the condition value contains phrases surrounded
 * by '...' or wildcard search with * or ?.
 */
public static MCRCondition<Void> normalizeCondition(MCRCondition<Void> cond) {
    if (cond == null) {
        return null;
    } else if (cond instanceof MCRSetCondition) {
        MCRSetCondition<Void> sc = (MCRSetCondition<Void>) cond;
        List<MCRCondition<Void>> children = sc.getChildren();
        sc = sc instanceof MCRAndCondition ? new MCRAndCondition<>() : new MCROrCondition<>();
        for (MCRCondition<Void> child : children) {
            child = normalizeCondition(child);
            if (child == null) {
            } else if (child instanceof MCRSetCondition && sc.getOperator().equals(((MCRSetCondition) child).getOperator())) {
                // Replace (a AND (b AND c)) with (a AND b AND c), same for OR
                sc.addAll(((MCRSetCondition<Void>) child).getChildren());
            } else {
                sc.addChild(child);
            }
        }
        children = sc.getChildren();
        if (children.size() == 0) {
            // Completely remove empty AND condition
            return null;
        } else if (children.size() == 1) {
            // Replace AND with just one child
            return children.get(0);
        } else {
            return sc;
        }
    } else if (cond instanceof MCRNotCondition) {
        MCRNotCondition<Void> nc = (MCRNotCondition<Void>) cond;
        MCRCondition<Void> child = normalizeCondition(nc.getChild());
        if (child == null) {
            // Remove empty NOT
            return null;
        } else if (child instanceof MCRNotCondition) {
            return normalizeCondition(((MCRNotCondition<Void>) child).getChild());
        } else {
            return new MCRNotCondition<>(child);
        }
    } else if (cond instanceof MCRQueryCondition) {
        MCRQueryCondition qc = (MCRQueryCondition) cond;
        if (!qc.getOperator().equals("contains")) {
            return qc;
        }
        // Normalize value when contains operator is used
        List<String> values = new ArrayList<>();
        StringBuilder phrase = null;
        StringTokenizer st = new StringTokenizer(qc.getValue(), " ");
        while (st.hasMoreTokens()) {
            String value = st.nextToken();
            if (// we are within phrase
            phrase != null) {
                if (// end of phrase
                value.endsWith("'")) {
                    value = phrase + " " + value;
                    values.add(value);
                    phrase = null;
                } else // in middle of phrase
                {
                    phrase.append(' ').append(value);
                }
            } else if (// begin of phrase
            value.startsWith("'")) {
                if (// one-word phrase
                value.endsWith("'")) {
                    values.add(value.substring(1, value.length() - 1));
                } else {
                    phrase = new StringBuilder(value);
                }
            } else if (// begin of NOT phrase
            value.startsWith("-'")) {
                if (// one-word phrase
                value.endsWith("'")) {
                    values.add("-" + value.substring(2, value.length() - 1));
                } else {
                    phrase = new StringBuilder(value);
                }
            } else {
                values.add(value);
            }
        }
        MCRAndCondition<Void> ac = new MCRAndCondition<>();
        for (String value : values) {
            if (value.startsWith("'")) {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "phrase", value.substring(1, value.length() - 1)));
            } else if (value.startsWith("-'")) {
                ac.addChild(new MCRNotCondition<>(new MCRQueryCondition(qc.getFieldName(), "phrase", value.substring(2, value.length() - 1))));
            } else if (value.contains("*") || value.contains("?")) {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "like", value));
            } else if (// -word means "NOT word"
            value.startsWith("-")) {
                MCRCondition<Void> subCond = new MCRQueryCondition(qc.getFieldName(), "contains", value.substring(1));
                ac.addChild(new MCRNotCondition<>(subCond));
            } else {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "contains", value));
            }
        }
        if (values.size() == 1) {
            return ac.getChildren().get(0);
        } else {
            return ac;
        }
    } else {
        return cond;
    }
}
Also used : MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) StringTokenizer(java.util.StringTokenizer) MCRCondition(org.mycore.parsers.bool.MCRCondition) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with MCRCondition

use of org.mycore.parsers.bool.MCRCondition in project mycore by MyCoRe-Org.

the class MCRConditionTransformer method getIndex.

/**
 * Returns the ID of the index of all fields referenced in this condition.
 * If the fields come from multiple indexes, the constant mixed is returned.
 */
@SuppressWarnings("rawtypes")
private static String getIndex(MCRCondition cond) {
    if (cond instanceof MCRQueryCondition) {
        MCRQueryCondition queryCondition = ((MCRQueryCondition) cond);
        String fieldName = queryCondition.getFieldName();
        return getIndex(fieldName);
    } else if (cond instanceof MCRNotCondition) {
        return getIndex(((MCRNotCondition) cond).getChild());
    }
    @SuppressWarnings("unchecked") List<MCRCondition> children = ((MCRSetCondition) cond).getChildren();
    // mixed indexes here!
    return children.stream().map(MCRConditionTransformer::getIndex).reduce((l, r) -> l.equals(r) ? l : mixed).get();
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition) Iterator(java.util.Iterator) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) Set(java.util.Set) HashMap(java.util.HashMap) MCRConfiguration(org.mycore.common.config.MCRConfiguration) Collectors(java.util.stream.Collectors) MCRException(org.mycore.common.MCRException) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) Logger(org.apache.logging.log4j.Logger) MCRSortBy(org.mycore.services.fieldquery.MCRSortBy) MCRSolrConstants(org.mycore.solr.MCRSolrConstants) Map(java.util.Map) SolrQuery(org.apache.solr.client.solrj.SolrQuery) MCRSolrUtils(org.mycore.solr.MCRSolrUtils) ORDER(org.apache.solr.client.solrj.SolrQuery.ORDER) LogManager(org.apache.logging.log4j.LogManager) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) SortClause(org.apache.solr.client.solrj.SolrQuery.SortClause) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) MCRCondition(org.mycore.parsers.bool.MCRCondition) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition)

Example 3 with MCRCondition

use of org.mycore.parsers.bool.MCRCondition in project mycore by MyCoRe-Org.

the class MCRQLSearchUtils method buildDefaultQuery.

/**
 * Search in default search field specified by MCR.SearchServlet.DefaultSearchField
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public static MCRQuery buildDefaultQuery(String search, String defaultSearchField) {
    String[] fields = defaultSearchField.split(" *, *");
    MCROrCondition queryCondition = new MCROrCondition();
    for (String fDef : fields) {
        MCRCondition condition = new MCRQueryCondition(fDef, "=", search);
        queryCondition.addChild(condition);
    }
    return new MCRQuery(MCRQueryParser.normalizeCondition(queryCondition));
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) MCRQuery(org.mycore.services.fieldquery.MCRQuery)

Example 4 with MCRCondition

use of org.mycore.parsers.bool.MCRCondition in project mycore by MyCoRe-Org.

the class MCRConditionTransformer method handleNotCondition.

@SuppressWarnings("rawtypes")
private static StringBuilder handleNotCondition(MCRNotCondition notCond, Set<String> usedFields) {
    MCRCondition child = notCond.getChild();
    StringBuilder sb = new StringBuilder();
    sb.append("-");
    StringBuilder solrQueryString = toSolrQueryString(child, usedFields, true);
    stripPlus(solrQueryString);
    if (solrQueryString == null || solrQueryString.length() == 0) {
        return null;
    }
    sb.append(solrQueryString);
    return sb;
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition)

Example 5 with MCRCondition

use of org.mycore.parsers.bool.MCRCondition in project mycore by MyCoRe-Org.

the class MCRConditionTransformer method buildMergedSolrQuery.

/**
 * Builds SOLR query.
 *
 * Automatically builds JOIN-Query if content search fields are used in query.
 * @param sortBy sort criteria
 * @param not true, if all conditions should be negated
 * @param and AND or OR connective between conditions
 * @param table conditions per "content" or "metadata"
 * @param maxHits maximum hits
 */
@SuppressWarnings("rawtypes")
public static SolrQuery buildMergedSolrQuery(List<MCRSortBy> sortBy, boolean not, boolean and, HashMap<String, List<MCRCondition>> table, int maxHits, List<String> returnFields) {
    List<MCRCondition> queryConditions = table.get("metadata");
    MCRCondition combined = buildSubCondition(queryConditions, and, not);
    SolrQuery solrRequestQuery = getSolrQuery(combined, sortBy, maxHits, returnFields);
    for (Map.Entry<String, List<MCRCondition>> mapEntry : table.entrySet()) {
        if (!mapEntry.getKey().equals("metadata")) {
            MCRCondition combinedFilterQuery = buildSubCondition(mapEntry.getValue(), and, not);
            SolrQuery filterQuery = getSolrQuery(combinedFilterQuery, sortBy, maxHits, returnFields);
            solrRequestQuery.addFilterQuery(MCRSolrConstants.JOIN_PATTERN + filterQuery.getQuery());
        }
    }
    return solrRequestQuery;
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) SolrQuery(org.apache.solr.client.solrj.SolrQuery)

Aggregations

MCRCondition (org.mycore.parsers.bool.MCRCondition)7 ArrayList (java.util.ArrayList)5 List (java.util.List)5 SolrQuery (org.apache.solr.client.solrj.SolrQuery)4 MCROrCondition (org.mycore.parsers.bool.MCROrCondition)4 MCRSetCondition (org.mycore.parsers.bool.MCRSetCondition)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 MCRAndCondition (org.mycore.parsers.bool.MCRAndCondition)3 MCRNotCondition (org.mycore.parsers.bool.MCRNotCondition)3 MCRQueryCondition (org.mycore.services.fieldquery.MCRQueryCondition)3 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 LogManager (org.apache.logging.log4j.LogManager)2 Logger (org.apache.logging.log4j.Logger)2 ORDER (org.apache.solr.client.solrj.SolrQuery.ORDER)2 SortClause (org.apache.solr.client.solrj.SolrQuery.SortClause)2 MCRException (org.mycore.common.MCRException)2