Page 1 of 1

How to execute this solr query?

Posted: Thu Jul 31, 2014 6:23 am
by gowthamgutha
I would like to get the minimum price and maximum price for the queried products.

http://localhost:8983/solr/select?q=*:*&stats=true&stats.field=price&rows=0&indent=true

How could I query this with embedded solr and How do I get in the facetFilter template?
The thing is it returns only the statistics but not the documents? So, when querying I'll get either documents or stats? How could I get both?

Thanks in advance. Hope you will reply as soon as possible.

Re: How to execute this solr query?

Posted: Wed Aug 06, 2014 3:27 pm
by RapidTransit
Be careful with stats query, because the stats will only return with the current query ie you search for Widgets in between $1 - $100, if you do a new range query for products between $25 - $50, your stats will now return 25 - 50.
You should do 2 separate queries if any facets are active.

Here's some things that may help you, what this does is extends FieldImpl to pass in the min and max stats. With a bit of extra stuff, the url params instead of looking like this: price=range[10:100], if I assign min post fix to say '-min' and my max postfix to '-max' and I set isAdHocRange = true. My new urls can now look like: price-min=10&price-max=100 to use with something like this http://refreshless.com/nouislider/ , requestmin and requestmax is to pass what ever the current range is in the url to the slider defaults the handles to those positions

Code: Select all


@Entity
@Table(name = "PSS_FIELD_EXTENSION")
public class FieldExtensionImpl extends FieldImpl implements FieldExtension, Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "AD_HOC_RANGE")
    protected Boolean isAdHocRange = false;

    @Column(name = "MIN_POST_FIX")
    protected String minPostfix;

    @Column(name = "MAX_POST_FIX")
    protected String maxPostfix;

    @Column(name = "INCREMENT")
    protected BigDecimal increment;

    @Column(name="SORTABLE")
    protected Boolean isSortable = false;

    @Transient
    protected Integer minValue;

    @Transient
    protected Integer maxValue;

    @Transient
    protected BigDecimal requestMin;

    @Transient
    protected BigDecimal requestMax;

    @Override
    public Boolean getIsAdHocRange() {
        return isAdHocRange;
    }

    @Override
    public void setIsAdHocRange(Boolean isAdHocRange) {
        this.isAdHocRange = isAdHocRange;
    }

    @Override
    public String getMinPostfix() {
        return minPostfix;
    }

    @Override
    public void setMinPostfix(String minPostfix) {
        this.minPostfix = minPostfix;
    }

    @Override
    public String getMaxPostfix() {
        return maxPostfix;
    }

    @Override
    public void setMaxPostfix(String maxPostfix) {
        this.maxPostfix = maxPostfix;
    }

    @Override
    public BigDecimal getIncrement() {
        return increment != null ? increment : new BigDecimal(1);
    }

    @Override
    public void setIncrement(BigDecimal increment) {
        this.increment = increment;
    }

    @Override
    public String getFormattedName() {
        return getAbbreviation() + "_" + getFacetFieldType().getType();
    }

    @Override
    public String getFormattedMinName() {
        return getAbbreviation() + getMinPostfix();
    }

    @Override
    public String getFormattedMaxName() {
        return getAbbreviation() + getMaxPostfix();
    }

    @Override
    public Integer getMinValue() {
        return minValue;
    }

    @Override
    public void setMinValue(Integer minValue) {
        this.minValue = minValue;
    }

    @Override
    public Integer getMaxValue() {
        return maxValue;
    }

    @Override
    public void setMaxValue(Integer maxValue) {
        this.maxValue = maxValue;
    }

    @Override
    public BigDecimal getRequestMin() {
        return requestMin != null ? requestMin : new BigDecimal(minValue);
    }

    @Override
    public void setRequestMin(BigDecimal requestMin) {
        this.requestMin = requestMin;
    }

    @Override
    public BigDecimal getRequestMax() {
        return requestMax != null ? requestMax : new BigDecimal(maxValue);
    }

    @Override
    public void setRequestMax(BigDecimal requestMax) {
        this.requestMax = requestMax;
    }

    @Override
    public Boolean getIsSortable() {
        return isSortable;
    }

    @Override
    public void setIsSortable(Boolean isSortable) {
        this.isSortable = isSortable;
    }

    @Override
    public String toJsonString() {
        final StringBuilder sb = new StringBuilder(getAbbreviation()).append(":{");
        sb.append("abbreviation:'").append(getAbbreviation()).append('\'');
        sb.append(", isAdHocRange:").append(isAdHocRange);
        sb.append(", entityType:'").append(entityType).append('\'');
        sb.append(", formattedName:'").append(getFormattedName()).append('\'');
        if(isAdHocRange) {
            sb.append(", rangeInfo: {");
            sb.append("increment:").append(getIncrement());
            sb.append(", minValue:").append(minValue);
            sb.append(", maxValue:").append(maxValue);
            sb.append(", requestMin:").append(getRequestMin());
            sb.append(", requestMax:").append(getRequestMax());
            sb.append(", formattedMinName:'").append(getFormattedMinName()).append('\'');
            sb.append(", formattedMaxName:'").append(getFormattedMaxName()).append('\'');
            sb.append("}");
        }
        sb.append('}');
        return sb.toString();
    }

}

Add this to my own extension of SolrSearchServiceImpl

Code: Select all

    private void getFacet(SearchCriteria searchCriteria, List<String> queryParams, Map.Entry<String, String[]> param, Map.Entry<String, SearchFacetDTO> dtoEntry) {
        FieldExtension fieldExtension = (FieldExtension) dtoEntry.getValue().getFacet().getField();
        if(fieldExtension.getAbbreviation().equals(param.getKey())){
            for(String p : param.getValue()){
                queryParams.add(fieldExtension.getFormattedName()+ ":\"" + p + "\"");
            }
            dtoEntry.getValue().setActive(true);
        } else  if(fieldExtension.getIsAdHocRange()){
                String facetName = fieldExtension.getFormattedMinName();
                BigDecimal start = BigDecimalValidator.getInstance().validate(param.getValue()[0]);
                BigDecimal end = null;
                if(facetName.equals(param.getKey()) && start != null){
                    if(searchCriteria.getFilterCriteria().containsKey(fieldExtension.getFormattedMaxName())){
                        end = BigDecimalValidator.getInstance().validate(searchCriteria.getFilterCriteria().get(fieldExtension.getFormattedMaxName())[0]);
                    }
                    ((FieldExtension) dtoEntry.getValue().getFacet().getField()).setRequestMin(start);
                    if(end != null){
                        ((FieldExtension) dtoEntry.getValue().getFacet().getField()).setRequestMax(end);
                        queryParams.add(fieldExtension.getFormattedName() + ":[" + start.toString() + " TO " + end.toString() + "]");
                    }else{
                        queryParams.add(fieldExtension.getFormattedName() + ":[" + start.toString() + " TO *]");
                    }
                }

            dtoEntry.getValue().setActive(true);
        }
    }


Code: Select all

    private QueryResponse getStatQuery(String qualifiedSolrQuery, String[] filterQueries) throws ServiceException {
        SolrQuery statQuery = new SolrQuery().setQuery(qualifiedSolrQuery);
        statQuery.setParam("stats", true);
        List<Field> rangeFields = ((FieldDaoExtension) fieldDao).readAllRangeFields();
        String[] statFields = new String[rangeFields.size()];
        for(int i = 0; i <  rangeFields.size(); i++){
            statFields[i] = ((FieldExtension) rangeFields.get(i)).getFormattedName();
        }
        statQuery.add("stats.field", statFields);
        statQuery.setFilterQueries(filterQueries);
        QueryResponse stats;
        try {
            stats = SolrContext.getServer().query(statQuery);
        }
        catch (SolrServerException e) {
            throw new ServiceException("Could not perform search", e);
        }
        return stats;
    }


Modified the body of findSearchResults

Code: Select all

...
QueryResponse stats = getStatQuery(qualifiedSolrQuery, filterQueries);

    for(SearchFacetDTO facet : facets){
            if(((FieldExtension) facet.getFacet().getField()).getIsAdHocRange() != null && ((FieldExtension) facet.getFacet().getField()).getIsAdHocRange()) {
                if (stats.getFieldStatsInfo().containsKey(((FieldExtension) facet.getFacet().getField()).getFormattedName())) {
                    Double validateMin = new DoubleValidator().validate(stats.getFieldStatsInfo().get(((FieldExtension) facet.getFacet().getField()).getFormattedName()).getMin().toString());
                    Double validateMax = new DoubleValidator().validate(stats.getFieldStatsInfo().get(((FieldExtension) facet.getFacet().getField()).getFormattedName()).getMax().toString());
                    if(validateMin != null ){
                        Double min = Math.floor(validateMin);
                        ((FieldExtension) facet.getFacet().getField()).setMinValue(min.intValue());
                    }
                    if(validateMax != null){

                        Double max = Math.ceil(validateMax);
                        ((FieldExtension) facet.getFacet().getField()).setMaxValue(max.intValue());
                    }
                }
            }
        }
...

Re: How to execute this solr query?

Posted: Wed Aug 06, 2014 3:30 pm
by RapidTransit
Also I recommend that you use commons validators for any numbers to make sure you don't throw an exception but instead just ignore the bad value.