All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.search.join.FiltersQParser Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.apache.solr.search.join;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
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 org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SyntaxError;

public class FiltersQParser extends QParser {

  protected String getFiltersParamName() {
    return "param";
  }

  protected FiltersQParser(
      String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
    super(qstr, localParams, params, req);
  }

  @Override
  public Query parse() throws SyntaxError {
    BooleanQuery query = parseImpl();
    return !query.clauses().isEmpty() ? wrapSubordinateClause(query) : noClausesQuery();
  }

  protected BooleanQuery parseImpl() throws SyntaxError {
    Map clauses = clauses();

    exclude(clauses.keySet());

    BooleanQuery.Builder builder = createBuilder();
    for (Map.Entry clause : clauses.entrySet()) {
      builder.add(unwrapQuery(clause.getKey().getQuery(), clause.getValue()), clause.getValue());
    }
    // what about empty query?
    return builder.build();
  }

  protected BooleanQuery.Builder createBuilder() {
    return new BooleanQuery.Builder();
  }

  protected Query unwrapQuery(Query query, BooleanClause.Occur occur) {
    return query;
  }

  protected Query wrapSubordinateClause(Query subordinate) throws SyntaxError {
    return subordinate;
  }

  protected Query noClausesQuery() throws SyntaxError {
    return new MatchAllDocsQuery();
  }

  protected void exclude(Collection clauses) {
    Set tagsToExclude = new HashSet<>();
    String excludeTags = localParams.get("excludeTags");
    if (excludeTags != null) {
      tagsToExclude.addAll(StrUtils.splitSmart(excludeTags, ','));
    }
    Map tagMap = (Map) req.getContext().get("tags");
    final Collection excludeSet;
    if (tagMap != null && !tagMap.isEmpty() && !tagsToExclude.isEmpty()) {
      excludeSet = excludeSet(tagMap, tagsToExclude);
    } else {
      excludeSet = Collections.emptySet();
    }
    clauses.removeAll(excludeSet);
  }

  protected Map clauses() throws SyntaxError {
    String[] params = localParams.getParams(getFiltersParamName());
    if (params != null && params.length == 0) { // never happens
      throw new SyntaxError(
          "Local parameter "
              + getFiltersParamName()
              + " is not defined for "
              + stringIncludingLocalParams);
    }
    IdentityHashMap clauses = new IdentityHashMap<>();

    for (String filter : params == null ? new String[0] : params) {
      if (filter == null || filter.length() == 0) {
        // it is ok to specify a filter param that is not present
        continue;
      }
      // as a side effect, qparser is mapped by tags in req context
      QParser parser = subQuery(filter, null);
      clauses.put(parser, BooleanClause.Occur.FILTER);
    }
    String queryText = localParams.get(QueryParsing.V);
    if (queryText != null && queryText.length() > 0) {
      QParser parser = subQuery(queryText, null);
      clauses.put(parser, BooleanClause.Occur.MUST);
    }
    return clauses;
  }

  private Collection excludeSet(Map tagMap, Set tagsToExclude) {

    IdentityHashMap excludeSet = new IdentityHashMap<>();
    for (String excludeTag : tagsToExclude) {
      Object olst = tagMap.get(excludeTag);
      // tagMap has entries of List>, but subject to change in the future
      if (!(olst instanceof Collection)) continue;
      for (Object o : (Collection) olst) {
        if (!(o instanceof QParser)) continue;
        QParser qp = (QParser) o;
        excludeSet.put(qp, Boolean.TRUE);
      }
    }
    return excludeSet.keySet();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy