Package org.springframework.data.solr.core

Source Code of org.springframework.data.solr.core.DefaultQueryParser

/*
* Copyright 2012 - 2014 the original author or authors.
*
* Licensed 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.springframework.data.solr.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.params.GroupParams;
import org.apache.solr.common.params.HighlightParams;
import org.apache.solr.common.params.StatsParams;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.solr.VersionUtil;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.FacetOptions;
import org.springframework.data.solr.core.query.FacetOptions.FacetParameter;
import org.springframework.data.solr.core.query.FacetOptions.FieldWithFacetParameters;
import org.springframework.data.solr.core.query.FacetQuery;
import org.springframework.data.solr.core.query.Field;
import org.springframework.data.solr.core.query.FilterQuery;
import org.springframework.data.solr.core.query.Function;
import org.springframework.data.solr.core.query.GroupOptions;
import org.springframework.data.solr.core.query.HighlightOptions;
import org.springframework.data.solr.core.query.HighlightOptions.FieldWithHighlightParameters;
import org.springframework.data.solr.core.query.HighlightOptions.HighlightParameter;
import org.springframework.data.solr.core.query.HighlightQuery;
import org.springframework.data.solr.core.query.Query;
import org.springframework.data.solr.core.query.QueryParameter;
import org.springframework.data.solr.core.query.SolrDataQuery;
import org.springframework.data.solr.core.query.StatsOptions;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
* Implementation of {@link QueryParser}. <br/>
* Creates executable {@link SolrQuery} from {@link Query} by traversing {@link Criteria}. Reserved characters like
* {@code +} or {@code -} will be escaped to form a valid query.
*
* @author Christoph Strobl
* @author John Dorman
* @author Rosty Kerei
* @author Luke Corpe
* @author Andrey Paramonov
* @author Philipp Jardas
* @author Francisco Spaeth
*/
public class DefaultQueryParser extends QueryParserBase<SolrDataQuery> {

  /**
   * Convert given Query into a SolrQuery executable via {@link org.apache.solr.client.solrj.SolrServer}
   *
   * @param query
   * @return
   */
  @Override
  public final SolrQuery doConstructSolrQuery(SolrDataQuery query) {
    Assert.notNull(query, "Cannot construct solrQuery from null value.");
    Assert.notNull(query.getCriteria(), "Query has to have a criteria.");

    SolrQuery solrQuery = new SolrQuery();
    solrQuery.setParam(CommonParams.Q, getQueryString(query));
    if (query instanceof Query) {
      processQueryOptions(solrQuery, (Query) query);
    }
    if (query instanceof FacetQuery) {
      processFacetOptions(solrQuery, (FacetQuery) query);
    }
    if (query instanceof HighlightQuery) {
      processHighlightOptions(solrQuery, (HighlightQuery) query);
    }
    return solrQuery;
  }

  private void processQueryOptions(SolrQuery solrQuery, Query query) {
    appendPagination(solrQuery, query.getOffset(), query.getRows());
    appendProjectionOnFields(solrQuery, query.getProjectionOnFields());
    appendFilterQuery(solrQuery, query.getFilterQueries());
    appendSort(solrQuery, query.getSort());
    appendDefaultOperator(solrQuery, query.getDefaultOperator());
    appendTimeAllowed(solrQuery, query.getTimeAllowed());
    appendDefType(solrQuery, query.getDefType());
    appendRequestHandler(solrQuery, query.getRequestHandler());

    processGroupOptions(solrQuery, query);
    processStatsOptions(solrQuery, query);
  }

  private void processFacetOptions(SolrQuery solrQuery, FacetQuery query) {
    if (enableFaceting(solrQuery, query)) {
      appendFacetingOnFields(solrQuery, (FacetQuery) query);
      appendFacetingQueries(solrQuery, (FacetQuery) query);
      appendFacetingOnPivot(solrQuery, (FacetQuery) query);
    }
  }

  private void setObjectNameOnGroupQuery(Query query, Object object, String name) {

    if (query instanceof NamedObjectsQuery) {
      ((NamedObjectsQuery) query).setName(object, name);
    }
  }

  private void processStatsOptions(SolrQuery solrQuery, Query query) {
    StatsOptions statsOptions = query.getStatsOptions();

    if (statsOptions == null
        || (CollectionUtils.isEmpty(statsOptions.getFields()) && CollectionUtils.isEmpty(statsOptions.getFacets()) && CollectionUtils
            .isEmpty(statsOptions.getSelectiveFacets()))) {
      return;
    }

    solrQuery.set(StatsParams.STATS, true);

    for (Field field : statsOptions.getFields()) {
      solrQuery.add(StatsParams.STATS_FIELD, field.getName());

      String selectiveCalcDistinctParam = CommonParams.FIELD + "." + field.getName() + "."
          + StatsParams.STATS_CALC_DISTINCT;
      Boolean selectiveCountDistincts = statsOptions.isSelectiveCalcDistincts(field);

      if (selectiveCountDistincts != null) {
        solrQuery.add(selectiveCalcDistinctParam, String.valueOf(selectiveCountDistincts.booleanValue()));
      }

    }

    for (Field field : statsOptions.getFacets()) {
      solrQuery.add(StatsParams.STATS_FACET, field.getName());
    }

    for (Entry<Field, Collection<Field>> entry : statsOptions.getSelectiveFacets().entrySet()) {

      Field field = entry.getKey();
      String prefix = CommonParams.FIELD + "." + field.getName() + ".";

      String paramName = prefix + StatsParams.STATS_FACET;
      for (Field facetField : entry.getValue()) {
        solrQuery.add(paramName, facetField.getName());
      }

    }

  }

  private void processGroupOptions(SolrQuery solrQuery, Query query) {

    GroupOptions groupOptions = query.getGroupOptions();

    if (groupOptions == null
        || (CollectionUtils.isEmpty(groupOptions.getGroupByFields())
            && CollectionUtils.isEmpty(groupOptions.getGroupByFunctions()) && CollectionUtils.isEmpty(groupOptions
            .getGroupByQueries()))) {
      return;
    }

    solrQuery.set(GroupParams.GROUP, true);
    solrQuery.set(GroupParams.GROUP_MAIN, groupOptions.isGroupMain());
    solrQuery.set(GroupParams.GROUP_FORMAT, "grouped");

    if (!CollectionUtils.isEmpty(groupOptions.getGroupByFields())) {
      for (Field field : groupOptions.getGroupByFields()) {
        solrQuery.add(GroupParams.GROUP_FIELD, field.getName());
      }
    }

    if (!CollectionUtils.isEmpty(groupOptions.getGroupByFunctions())) {
      for (Function function : groupOptions.getGroupByFunctions()) {
        String functionFragment = createFunctionFragment(function, 0);
        setObjectNameOnGroupQuery(query, function, functionFragment);
        solrQuery.add(GroupParams.GROUP_FUNC, functionFragment);
      }
    }

    if (!CollectionUtils.isEmpty(groupOptions.getGroupByQueries())) {
      for (Query groupQuery : groupOptions.getGroupByQueries()) {
        String queryFragment = getQueryString(groupQuery);
        setObjectNameOnGroupQuery(query, groupQuery, queryFragment);
        solrQuery.add(GroupParams.GROUP_QUERY, queryFragment);
      }
    }

    if (groupOptions.getSort() != null) {

      for (Order order : groupOptions.getSort()) {
        solrQuery.add(GroupParams.GROUP_SORT, order.getProperty().trim() + " "
            + (order.isAscending() ? ORDER.asc : ORDER.desc));
      }
    }

    if (groupOptions.getCachePercent() > 0) {
      solrQuery.add(GroupParams.GROUP_CACHE_PERCENTAGE, String.valueOf(groupOptions.getCachePercent()));
    }

    if (groupOptions.getLimit() != null && groupOptions.getLimit() >= 0) {
      solrQuery.set(GroupParams.GROUP_LIMIT, groupOptions.getLimit());
    }

    if (groupOptions.getOffset() != null && groupOptions.getOffset() >= 0) {
      solrQuery.set(GroupParams.GROUP_OFFSET, groupOptions.getOffset());
    }

    solrQuery.set(GroupParams.GROUP_TOTAL_COUNT, groupOptions.isTotalCount());
    solrQuery.set(GroupParams.GROUP_FACET, groupOptions.isGroupFacets());
    solrQuery.set(GroupParams.GROUP_TRUNCATE, groupOptions.isTruncateFacets());
  }

  /**
   * Append highlighting parameters to {@link SolrQuery}
   *
   * @param solrQuery
   * @param query
   */
  protected void processHighlightOptions(SolrQuery solrQuery, HighlightQuery query) {
    if (query.hasHighlightOptions()) {
      HighlightOptions highlightOptions = query.getHighlightOptions();
      solrQuery.setHighlight(true);
      if (!highlightOptions.hasFields()) {
        solrQuery.addHighlightField(HighlightOptions.ALL_FIELDS.getName());
      } else {
        for (Field field : highlightOptions.getFields()) {
          solrQuery.addHighlightField(field.getName());
        }
        for (FieldWithHighlightParameters fieldWithHighlightParameters : highlightOptions
            .getFieldsWithHighlightParameters()) {
          addPerFieldHighlightParameters(solrQuery, fieldWithHighlightParameters);
        }
      }
      for (HighlightParameter option : highlightOptions.getHighlightParameters()) {
        addOptionToSolrQuery(solrQuery, option);
      }
      if (highlightOptions.hasQuery()) {
        solrQuery.add(HighlightParams.Q, getQueryString(highlightOptions.getQuery()));
      }
    }
  }

  private void addOptionToSolrQuery(SolrQuery solrQuery, QueryParameter option) {
    if (option != null && StringUtils.isNotBlank(option.getName())) {
      solrQuery.add(option.getName(), conversionService.convert(option.getValue(), String.class));
    }
  }

  private void addFieldSpecificParameterToSolrQuery(SolrQuery solrQuery, Field field, QueryParameter option) {
    if (option != null && field != null && StringUtils.isNotBlank(option.getName())) {
      if (option.getValue() == null) {
        solrQuery.add(createPerFieldOverrideParameterName(field, option.getName()), (String) null);
      } else {
        String value = option.getValue().toString();
        if (conversionService.canConvert(option.getValue().getClass(), String.class)) {
          value = conversionService.convert(option.getValue(), String.class);
        }
        solrQuery.add(createPerFieldOverrideParameterName(field, option.getName()), value);
      }
    }
  }

  private void addPerFieldHighlightParameters(SolrQuery solrQuery, FieldWithHighlightParameters field) {
    for (HighlightParameter option : field) {
      addFieldSpecificParameterToSolrQuery(solrQuery, field, option);
    }
  }

  protected String createPerFieldOverrideParameterName(Field field, String parameterName) {
    return "f." + field.getName() + "." + parameterName;
  }

  private boolean enableFaceting(SolrQuery solrQuery, FacetQuery query) {
    FacetOptions facetOptions = query.getFacetOptions();
    if (facetOptions == null
        || (!facetOptions.hasFields() && !facetOptions.hasFacetQueries() && !facetOptions.hasPivotFields())) {
      return false;
    }
    solrQuery.setFacet(true);
    solrQuery.setFacetMinCount(facetOptions.getFacetMinCount());
    solrQuery.setFacetLimit(facetOptions.getPageable().getPageSize());
    if (facetOptions.getPageable().getPageNumber() > 0) {
      solrQuery.set(FacetParams.FACET_OFFSET, facetOptions.getPageable().getOffset());
    }
    if (FacetOptions.FacetSort.INDEX.equals(facetOptions.getFacetSort())) {
      solrQuery.setFacetSort(FacetParams.FACET_SORT_INDEX);
    }
    return true;
  }

  private void appendFacetingOnFields(SolrQuery solrQuery, FacetQuery query) {
    FacetOptions facetOptions = query.getFacetOptions();
    if (facetOptions.getPageable().getPageNumber() > 0) {
      solrQuery.set(FacetParams.FACET_OFFSET, facetOptions.getPageable().getOffset());
    }
    solrQuery.addFacetField(convertFieldListToStringArray(facetOptions.getFacetOnFields()));
    if (facetOptions.hasFacetPrefix()) {
      solrQuery.setFacetPrefix(facetOptions.getFacetPrefix());
    }
    for (FieldWithFacetParameters parametrizedField : facetOptions.getFieldsWithParameters()) {
      addPerFieldFacetParameters(solrQuery, parametrizedField);
      if (parametrizedField.getSort() != null && FacetOptions.FacetSort.INDEX.equals(parametrizedField.getSort())) {
        addFieldSpecificParameterToSolrQuery(solrQuery, parametrizedField, new FacetParameter(FacetParams.FACET_SORT,
            FacetParams.FACET_SORT_INDEX));
      }

    }
  }

  private void addPerFieldFacetParameters(SolrQuery solrQuery, FieldWithFacetParameters field) {
    for (FacetParameter parameter : field) {
      addFieldSpecificParameterToSolrQuery(solrQuery, field, parameter);
    }
  }

  private void appendFacetingQueries(SolrQuery solrQuery, FacetQuery query) {
    FacetOptions facetOptions = query.getFacetOptions();
    for (SolrDataQuery fq : facetOptions.getFacetQueries()) {
      String facetQueryString = getQueryString(fq);
      if (StringUtils.isNotBlank(facetQueryString)) {
        solrQuery.addFacetQuery(facetQueryString);
      }
    }
  }

  private void appendFacetingOnPivot(SolrQuery solrQuery, FacetQuery query) {
    if (VersionUtil.isSolr3XAvailable()) {
      throw new UnsupportedOperationException(
          "Pivot Facets are not available for solr version lower than 4.x - Please check your depdendencies.");
    }

    FacetOptions facetOptions = query.getFacetOptions();
    String[] pivotFields = convertFieldListToStringArray(facetOptions.getFacetOnPivots());
    solrQuery.addFacetPivotField(pivotFields);
  }

  /**
   * Set filter filter queries for {@link SolrQuery}
   *
   * @param solrQuery
   * @param filterQueries
   */
  protected void appendFilterQuery(SolrQuery solrQuery, List<FilterQuery> filterQueries) {
    if (CollectionUtils.isEmpty(filterQueries)) {
      return;
    }
    List<String> filterQueryStrings = getFilterQueryStrings(filterQueries);

    if (!filterQueryStrings.isEmpty()) {
      solrQuery.setFilterQueries(convertStringListToArray(filterQueryStrings));
    }
  }

  /**
   * Append sorting parameters to {@link SolrQuery}
   *
   * @param solrQuery
   * @param sort
   */
  @SuppressWarnings("deprecation")
  protected void appendSort(SolrQuery solrQuery, Sort sort) {
    if (sort == null) {
      return;
    }

    for (Order order : sort) {
      // addSort which is to be used instead of addSortField is not available in versions below 4.2.0
      if (VersionUtil.isSolr420Available()) {
        solrQuery.addSort(order.getProperty(), order.isAscending() ? ORDER.asc : ORDER.desc);
      } else {
        solrQuery.addSortField(order.getProperty(), order.isAscending() ? ORDER.asc : ORDER.desc);
      }
    }
  }

  private String[] convertFieldListToStringArray(List<? extends Field> fields) {
    String[] strResult = new String[fields.size()];
    for (int i = 0; i < fields.size(); i++) {
      strResult[i] = fields.get(i).getName();
    }
    return strResult;
  }

  private String[] convertStringListToArray(List<String> listOfString) {
    String[] strResult = new String[listOfString.size()];
    listOfString.toArray(strResult);
    return strResult;
  }

  private List<String> getFilterQueryStrings(List<FilterQuery> filterQueries) {
    List<String> filterQueryStrings = new ArrayList<String>(filterQueries.size());

    for (FilterQuery filterQuery : filterQueries) {
      String filterQueryString = getQueryString(filterQuery);
      if (StringUtils.isNotBlank(filterQueryString)) {
        filterQueryStrings.add(filterQueryString);
      }
    }
    return filterQueryStrings;
  }

}
TOP

Related Classes of org.springframework.data.solr.core.DefaultQueryParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.