Index: branches/pssGrails3/grails-app/services/com/lemanscorp/search/solr/SolrRequestService.groovy =================================================================== diff -u -r8884 -r8886 --- branches/pssGrails3/grails-app/services/com/lemanscorp/search/solr/SolrRequestService.groovy (.../SolrRequestService.groovy) (revision 8884) +++ branches/pssGrails3/grails-app/services/com/lemanscorp/search/solr/SolrRequestService.groovy (.../SolrRequestService.groovy) (revision 8886) @@ -1,529 +1,542 @@ package com.lemanscorp.search.solr - -import groovy.sql.Sql +import com.lemans.services.LemansService import groovy.xml.MarkupBuilder - -import javax.annotation.Resource - import org.springframework.transaction.annotation.Isolation import org.springframework.transaction.annotation.Transactional +class SolrRequestService extends LemansService { -class SolrRequestService { + def solrService - @Resource - Sql sql + /** add predefined facets - to avoid sending other params to solr (xyz_FC) to avoid failure*/ + def facetNames = ['dm', 'ci', 'ct1', 'ct2', 'ct3', 'ct4', 'br', 'cc', 'sc', 'mk', 'md', 'yr', 'ps', 'pr', 'pn', 'dps', 'sg', 'pv', + 'sv', 'pc'] - def solrService + static final RIDER_DOMAIN = 18..24 - /** add predefined facets - to avoid sending other params to solr (xyz_FC) to avoid failure*/ - def facetNames = ['dm','ci','ct1','ct2','ct3','ct4','br','cc','sc','mk','md','yr','ps','pr', 'pn', 'dps', 'sg', 'pv', 'sv', 'pc'] + static final int PNW_DOMAIN = 4 - def static final riderDomain = 18..24 + /** + * create selected facets list from request parameters. + * If parameter name is av* add additional facet field av to get av_FC facet. + * @param params + * @return + */ + Map getSelectedFacets(Object params) { + def selectedFacets = [:] + params.keySet().each { pName -> + if (pName.startsWith('av')) { + selectedFacets.put(pName, params.list(pName)) + selectedFacets.put('av', ['av']) + } else if (facetNames.contains(pName)) { + selectedFacets.put(pName, params.list(pName)) + //added to handle APPDEV-5429 -- Adding facet would indicate solrConfig SP to pull next set of facets + } else if (pName.contains('Filter')) { + String filterFacetName = pName.split('_')[0] + if (facetNames.contains(filterFacetName)) { + selectedFacets.put(filterFacetName, params.list(pName)) + } + } + } - static final int pnwDomain = 4 - /** - * create selected facets list from request parameters. - * If parameter name is av* add additional facet field av to get av_FC facet. - * @param params - * @return - */ - Map getSelectedFacets(Object params){ - def selectedFacets = [:] - params.keySet().each { pName-> - if(pName.startsWith('av')){ - selectedFacets.put(pName, params.list(pName)) - selectedFacets.put('av',['av']) - } else if (facetNames.contains(pName)) { - selectedFacets.put(pName, params.list(pName)) - //added to handle APPDEV-5429 -- Adding facet would indicate solrConfig SP to pull next set of facets - } else if (pName.contains("Filter")) { - String filterFacetName =pName.split("_")[0] - if(facetNames.contains(filterFacetName)) { - selectedFacets.put(filterFacetName, params.list(pName)) - } - } - } + selectedFacets + } + /** + * Generate filter query string based on selected facets and values + * @param params + * @param selectedFacetsMap + * @param core + * @return + */ + String createFilterQS(Object params, Object selectedFacetsMap, domainConfigFacets, core) { - return selectedFacets - } + def qualifier = createQualifier(params, selectedFacetsMap, domainConfigFacets, true, core) + def qString = qualifier + def genParams = '' + def domainFacet + if (params.pv) { + domainFacet = solrService.findDomainConfigFor('pv', domainConfigFacets) + qualifier = selectedFacetsMap.get('pv').collect { item -> "primaryVendorId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.sv) { + domainFacet = solrService.findDomainConfigFor('sv', domainConfigFacets) + qualifier = selectedFacetsMap.get('sv').collect { item -> "secondaryVendorId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.pc) { + domainFacet = solrService.findDomainConfigFor('pc', domainConfigFacets) + qualifier = selectedFacetsMap.get('pc').collect { item -> "productCode:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.sg) { + domainFacet = solrService.findDomainConfigFor('sg', domainConfigFacets) + qualifier = selectedFacetsMap.get('sg').collect { item -> "segmentId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.br) { + domainFacet = solrService.findDomainConfigFor('br', domainConfigFacets) + qualifier = selectedFacetsMap.get('br').collect { item -> "brandId:$item" }.join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.br || params.br_Filter) { + if (params.br_Filter) { + //added to handle APPDEV-5429 -- + qualifier = params.list('br_Filter').collect { item -> "brandId:$item" }.join(' OR ') + qString += ' AND (' + qualifier + ')' + } else { + domainFacet = solrService.findDomainConfigFor('br', domainConfigFacets) + qualifier = selectedFacetsMap.get('br').collect { item -> "brandId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + } + if (params.md) { + domainFacet = solrService.findDomainConfigFor('md', domainConfigFacets) + qualifier = selectedFacetsMap.get('md').collect { item -> "modelId:$item" }.join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.yr) { + domainFacet = solrService.findDomainConfigFor('yr', domainConfigFacets) + qualifier = selectedFacetsMap.get('yr').collect { item -> "year:$item" }.join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.cc) { + domainFacet = solrService.findDomainConfigFor('cc', domainConfigFacets) + qualifier = selectedFacetsMap.get('cc').collect { item -> "comCodeId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.sc) { + domainFacet = solrService.findDomainConfigFor('sc', domainConfigFacets) + qualifier = selectedFacetsMap.get('sc').collect { item -> "subComCodeId:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + if (params.ps) { + domainFacet = solrService.findDomainConfigFor('ps', domainConfigFacets) + qualifier = selectedFacetsMap.get('ps').collect { item -> "partStatus:$item" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + //dps has id with hypen in it say -9993. So need to escape it. + if (params.dps) { + domainFacet = solrService.findDomainConfigFor('dps', domainConfigFacets) + qualifier = selectedFacetsMap.get('dps').collect { item -> "dps:${escapeQueryChars(item)}" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + //apply this only when catalog is selected + if (params.ci && (params.pn)) { + domainFacet = solrService.findDomainConfigFor('pn', domainConfigFacets) + qualifier = selectedFacetsMap.get('pn').collect { item -> "pn_FC:${params.ci}|${item}" } + .join(' ' + domainFacet?.valueBooleanOperator + ' ') + qString += ' AND (' + qualifier + ')' + } + //filter by field (partNumber, productId, - called by psa to search by part number + params.keySet().each { String key -> + if (key?.startsWith('sf_')) { + def vals = params.list(key)?.minus('') ?: [] + qualifier = vals.findAll { + it?.trim() != '' + }?.collect { item -> "${key - 'sf_'}:${item}" }.join(' OR ') + if (qualifier) { + //added for PMO-1122 only when core is part search on xrefQualifier. + if (core == 'part') { + def xrefQualifer = vals.findAll { + it?.trim() != '' + }?.collect { item -> "xrefPartNumber:${item}" }.join(' OR ') + qualifier += ' OR ' + xrefQualifer + } + qString += ' AND (' + qualifier + ')' + } + } + } - /** - * Generate filter query string based on selected facets and values - * @param params - * @param selectedFacetsMap - * @param core - * @return - */ - String createFilterQS(Object params, Object selectedFacetsMap, domainConfigFacets, core) { + def str = '' + params.keySet().each { String key -> - def qualifier = createQualifier(params, selectedFacetsMap, domainConfigFacets, true, core) - def qString = qualifier - def genParams = '' - def domainFacet - if (params.pv) { - domainFacet = solrService.findDomainConfigFor('pv', domainConfigFacets) - qualifier = selectedFacetsMap.get('pv').collect{ item -> "primaryVendorId:$item" }.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if (params.sv) { - domainFacet = solrService.findDomainConfigFor('sv', domainConfigFacets) - qualifier = selectedFacetsMap.get('sv').collect{ item -> "secondaryVendorId:$item" }.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if (params.pc) { - domainFacet = solrService.findDomainConfigFor('pc', domainConfigFacets) - qualifier = selectedFacetsMap.get('pc').collect{ item -> "productCode:$item" }.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.sg){ - domainFacet = solrService.findDomainConfigFor('sg', domainConfigFacets) - qualifier = selectedFacetsMap.get('sg').collect{item -> "segmentId:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.br){ - domainFacet = solrService.findDomainConfigFor('br', domainConfigFacets) - qualifier = selectedFacetsMap.get('br').collect{item -> "brandId:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.br || params.br_Filter){ - if(!params.br_Filter) { - domainFacet = solrService.findDomainConfigFor('br', domainConfigFacets) - qualifier = selectedFacetsMap.get('br').collect { item -> "brandId:$item" }.join(" " + domainFacet?.valueBooleanOperator + " ") - qString += " AND (" + qualifier + ")" - } else { - //added to handle APPDEV-5429 -- - qualifier = params.list('br_Filter').collect { item -> "brandId:$item" }.join(" OR ") - qString += " AND (" + qualifier + ")" - } - } - if(params.md){ - domainFacet = solrService.findDomainConfigFor('md', domainConfigFacets) - qualifier = selectedFacetsMap.get('md').collect{item -> "modelId:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.yr){ - domainFacet = solrService.findDomainConfigFor('yr', domainConfigFacets) - qualifier = selectedFacetsMap.get('yr').collect{item -> "year:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.cc){ - domainFacet = solrService.findDomainConfigFor('cc', domainConfigFacets) - qualifier = selectedFacetsMap.get('cc').collect{item -> "comCodeId:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.sc){ - domainFacet = solrService.findDomainConfigFor('sc', domainConfigFacets) - qualifier = selectedFacetsMap.get('sc').collect{item -> "subComCodeId:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - if(params.ps){ - domainFacet = solrService.findDomainConfigFor('ps', domainConfigFacets) - qualifier = selectedFacetsMap.get('ps').collect{item -> "partStatus:$item"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - //dps has id with hypen in it say -9993. So need to escape it. - if(params.dps){ - domainFacet = solrService.findDomainConfigFor('dps', domainConfigFacets) - qualifier = selectedFacetsMap.get('dps').collect{item -> "dps:${escapeQueryChars(item)}"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - //apply this only when catalog is selected - if(params.ci && (params.pn)) { - domainFacet = solrService.findDomainConfigFor('pn', domainConfigFacets) - qualifier = selectedFacetsMap.get('pn').collect{item -> "pn_FC:${params.ci}|${item}"}.join(" " + domainFacet?.valueBooleanOperator + " ") - qString +=" AND ("+qualifier+")" - } - //filter by field (partNumber, productId, - called by psa to search by part number - params.keySet().each { String key -> - if(key?.startsWith("sf_")){ - def vals = params.list(key)?.minus('')?:[] - qualifier = vals.findAll{it?.trim() != ''}?.collect{item -> "${key.minus('sf_')}:${item}"}.join(" " + 'OR' + " ") - if(qualifier) { - //added for PMO-1122 only when core is part search on xrefQualifier. - if(core == 'part'){ - def xrefQualifer = vals.findAll{it?.trim() != ''}?.collect{item -> "xrefPartNumber:${item}"}.join(" " + 'OR' + " ") - qualifier+=" "+"OR"+" "+xrefQualifer - } - qString +=" AND ("+qualifier+")" - } - } - } + if (key.startsWith('av')) { + def values = params."$key" + def attrNameId = key.substring('av'.length()) + str += ' AND (' + //str+=" AND (attributeNameId:${attrNameId} AND " + def paramValues = params.list(key) + //av_FC:191|*|5226|* OR av_FC:191|*|41531|* + paramValues.each { paramValue -> + str += "av_FC:${attrNameId}|*|${paramValue}|* OR " + } + str = str.substring(0, str.length() - ' OR '.length()) + str += ')' + } + } + if (str.length() > 0) { + str = str.substring(' AND '.length()) + str = '(' + str + ')' + qString += ' AND ' + str + } + //qString = "("+qString+")" + //replace above line with below code for solr4 regex search - def str = "" - params.keySet().each { String key -> + def fitmentQuery = '' + if (params.mk || params.yr || params.md) { + def mks = joinFitmentString(params.mk) + def yrs = joinFitmentString(params.yr) + def mds = joinFitmentString(params.md) + fitmentQuery = "AND (mk_yr_md_FC:/($mks)\\|(.+)\\|($yrs)\\|($mds)\\|(.+)/)" + //This should be mk_yr_md but part core do not have it - if(key.startsWith("av")){ - def values = params."$key" - def attrNameId = key.substring('av'.length()) - str+=" AND (" - //str+=" AND (attributeNameId:${attrNameId} AND " - def paramValues = params.list(key) - //av_FC:191|*|5226|* OR av_FC:191|*|41531|* - paramValues.each { paramValue -> - str+="av_FC:${attrNameId}|*|${paramValue}|* OR " - } - str = str.substring(0, str.length() -" OR ".length()) - str+=")" - } - } - if(str.length() > 0){ - str = str.substring(' AND '.length()) - str = "("+str+")" - qString+=" AND "+str - } - //qString = "("+qString+")" - //replace above line with below code for solr4 regex search + } + qString = '(' + qString + ' ' + fitmentQuery + ')' - def fitmentQuery = '' - if(params.mk || params.yr || params.md) { - def mks = joinFitmentString(params.mk) - def yrs = joinFitmentString(params.yr) - def mds = joinFitmentString(params.md) - fitmentQuery = "AND (mk_yr_md_FC:/($mks)\\|(.+)\\|($yrs)\\|($mds)\\|(.+)/)" //This should be mk_yr_md but part core do not have it + //filter specific rider only parts for all parts search made from riderDomains. + if (core == 'part' && (RIDER_DOMAIN.contains(params.int('dm')) || params.int('dm') == PNW_DOMAIN)) { + qString += " AND (dm_ci_ct1_ct2_ct3_ct4_pr:$params.dm||||||)" + } - } - qString = "("+qString+ " "+ fitmentQuery +")" + log.debug 'qString:' + qString + qString + } + //solr4 regex search + /** + * Join string for regular expression based search. Returns .+ for '*' wild card search + * @param items + * @return + */ + def joinFitmentString(items) { - //filter specific rider only parts for all parts search made from riderDomains. - if (core == 'part' && (riderDomain.contains(params.int('dm')) || params.int('dm') == pnwDomain)) { - qString += " AND (dm_ci_ct1_ct2_ct3_ct4_pr:$params.dm||||||)" - } + def itemStr = '' + //string - then do not split (could be 1 element) + if (items instanceof String) { + itemStr = items + } else { + //collection + itemStr = items?.collect { it -> it }?.join('|') + } + //return wild card for null or empty items + if (itemStr == null || itemStr?.trim() == '') { + itemStr = '.+' + } + itemStr + } - log.debug "qString:"+qString - return qString - } - //solr4 regex search - /** - * Join string for regular expression based search. Returns .+ for '*' wild card search - * @param items - * @return - */ + /** + * Create the qualifier with * for non selected entities + * @param params + * @param selectedFacetsMap + * @param domainConfigFacets + * @param isForParts + * @param core + * + * @return + */ + String createQualifier(Object params, Object selectedFacetsMap, domainConfigFacets, boolean isForParts, core) { + def fieldName = 'dm_ci_ct1_ct2_ct3_ct4_pr' + def qualifier + //for part core if domain specific fields (ci,ct*,pr,pg) are not selected use fq=(id:*) + //for other fields like br,avp (which are not domain specific) use fq=(id:*) filter + if (core == 'part' || core == 'inactivePart') { + //TODO:add locale specific logic + qualifier = 'id:*' + } else { + qualifier = "${fieldName}:${params.dm}|*|*|*|*|*|*" + } - def joinFitmentString(items) { + def domainFacet + def operator + if (params.pr) { + domainFacet = solrService.findDomainConfigFor('pr', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('pr').collect { item -> " ${fieldName}:${params.dm}|*|*|*|*|*|" + item }.join(" $operator ") + } else if (params.ct4) { + domainFacet = solrService.findDomainConfigFor('ct4', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('ct4').collect { item -> " ${fieldName}:${params.dm}|*|*|*|*|" + item + '|*' }.join(' ' + + "$operator ") + } else if (params.ct3) { + domainFacet = solrService.findDomainConfigFor('ct3', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('ct3').collect { item -> " ${fieldName}:${params.dm}|*|*|*|" + item + '|*|*' }.join(' ' + + "$operator ") + } else if (params.ct2) { + domainFacet = solrService.findDomainConfigFor('ct2', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('ct2').collect { item -> " ${fieldName}:${params.dm}|*|*|" + item + '|*|*|*' }.join(' ' + + "$operator ") + } else if (params.ct1) { + domainFacet = solrService.findDomainConfigFor('ct1', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('ct1').collect { item -> " ${fieldName}:${params.dm}|*|" + item + '|*|*|*|*' }.join(' ' + + "$operator ") + } else if (params.ci) { + domainFacet = solrService.findDomainConfigFor('ci', domainConfigFacets) + operator = isForParts ? domainFacet?.valueBooleanOperator : ' OR ' + qualifier = selectedFacetsMap.get('ci').collect { item -> " ${fieldName}:${params.dm}|" + item + '|*|*|*|*|*' }.join(' ' + + "$operator ") + } + //APPDEV-1750 - surround the qualifer with ( + '(' + qualifier + ')' + } - def itemStr = '' - //string - then do not split (could be 1 element) - if(items instanceof String) { - itemStr = items - } else { - //collection - itemStr = items?.collect{it->it}?.join("|") - } - //return wild card for null or empty items - if(itemStr == null || itemStr?.trim() == '') { - itemStr = '.+' - } - return itemStr - } + /** + * Create xml for selected Facets to send to store procedure + * @param selectedFacetsMap TODO + * @return + */ + String createSelectedFacetXml(Object selectedFacetsMap) { + def writer = new StringWriter() + def xml = new MarkupBuilder(writer) + xml.root { + (selectedFacetsMap.keySet() - 'av').each { pName -> + selectedFacetsMap.get(pName).each { pValue -> + facet(abbr: pName, valueId: pValue) + } + } + } + log.debug writer.toString() + writer.toString() + } + /** + * Get next facets from database + * @param domainId + * @return + */ + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + Expando getUIConfig(docType, domainId, selectedFacetsMap, q, locale) { - /** - * Create the qualifier with * for non selected entities - * @param params - * @param selectedFacetsMap - * @param domainConfigFacets - * @param isForParts - * @param core - * - * @return - */ - String createQualifier(Object params, Object selectedFacetsMap, domainConfigFacets, boolean isForParts, core){ - def fieldName ='dm_ci_ct1_ct2_ct3_ct4_pr' - def qualifier - //for part core if domain specific fields (ci,ct*,pr,pg) are not selected use fq=(id:*) - //for other fields like br,avp (which are not domain specific) use fq=(id:*) filter - if(core == 'part' || core=='inactivePart') { - //TODO:add locale specific logic - qualifier = "id:*" - } else { - qualifier = "${fieldName}:${params.dm}|*|*|*|*|*|*" - } + Expando uiConfig = new Expando() + def selectedFacetsXml + try { + List domainFacets = [] + List selectedFacets = [] + List nextFacets = [] + List renderers = [] + def relevancy = [] + def hitlistDoc - def domainFacet - def operator - if (params.pr) { - domainFacet = solrService.findDomainConfigFor('pr', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('pr').collect{item -> " ${fieldName}:${params.dm}|*|*|*|*|*|" + item}.join(" $operator ") - } else if (params.ct4) { - domainFacet = solrService.findDomainConfigFor('ct4', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('ct4').collect{item -> " ${fieldName}:${params.dm}|*|*|*|*|" + item + "|*"}.join(" $operator ") - } else if (params.ct3) { - domainFacet = solrService.findDomainConfigFor('ct3', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('ct3').collect{item -> " ${fieldName}:${params.dm}|*|*|*|" + item + "|*|*"}.join(" $operator ") - } else if (params.ct2) { - domainFacet = solrService.findDomainConfigFor('ct2', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('ct2').collect{item -> " ${fieldName}:${params.dm}|*|*|" + item + "|*|*|*"}.join(" $operator ") - } else if (params.ct1) { - domainFacet = solrService.findDomainConfigFor('ct1', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('ct1').collect{item -> " ${fieldName}:${params.dm}|*|" + item + "|*|*|*|*"}.join(" $operator ") - } else if (params.ci) { - domainFacet = solrService.findDomainConfigFor('ci', domainConfigFacets) - operator = isForParts?domainFacet?.valueBooleanOperator : ' OR ' - qualifier = selectedFacetsMap.get('ci').collect{item -> " ${fieldName}:${params.dm}|" + item + "|*|*|*|*|*"}.join(" $operator ") - } - //APPDEV-1750 - surround the qualifer with ( - return '('+qualifier+')' - } + /* create xml to sent to sp to get next facets */ + selectedFacetsXml = createSelectedFacetXml(selectedFacetsMap) + def sortBys = [] + log.debug "[$domainId, $selectedFacetsXml, $docType, $q]" - /** - * Create xml for selected Facets to send to store procedure - * @param selectedFacetsMap TODO - * @return - */ + log.debug(selectedFacetsXml) + def nextFacetXml + sql().query('{call spSolrConfiguration(@domainId=?, @selectedFacets=?, @docType=?, @q=?, @locale= ?)}', + [domainId, selectedFacetsXml, docType, q, locale]) { rs -> + while (rs.next()) { + nextFacetXml = rs.getString(1) + log.debug nextFacetXml + } + if (nextFacetXml) { + def root = new XmlSlurper().parseText(nextFacetXml) - String createSelectedFacetXml(Object selectedFacetsMap){ + //domain facets + root.config.facets.domain.facet.each { domainFacet -> + if (domainFacet.abbr == 'ct') { + domainFacet.abbr = 'ct1' + domainFacets.add(createDomainFacet(domainFacet)) + domainFacet.abbr = 'ct2' + domainFacets.add(createDomainFacet(domainFacet)) + domainFacet.abbr = 'ct3' + domainFacets.add(createDomainFacet(domainFacet)) + domainFacet.abbr = 'ct4' + domainFacets.add(createDomainFacet(domainFacet)) + } else { + domainFacets.add(createDomainFacet(domainFacet)) + } - def writer = new StringWriter() - def xml = new MarkupBuilder(writer) - xml.root() { - selectedFacetsMap.keySet().minus('av').each { pName-> - selectedFacetsMap.get(pName).each {pValue -> - facet(abbr:pName, valueId:pValue) - } - } - } - log.debug writer.toString() - return writer.toString() - } + } + //selected facets + root.config.facets.selected.facet.each { selectedFacet -> + selectedFacets.add(new Expando(abbr: selectedFacet.abbr as String + , valueId: selectedFacet?.valueId as String)) + } + //next facets + root.config.facets.next.facet.each { facet -> + nextFacets.add(new Expando(abbr: facet.abbr as String)) + } + root.config.page.each { page -> + renderers.add(page.renderer as String) + //add catalog /category page numbers + uiConfig.contextPageStart = page?.contextPageStart as String + uiConfig.contextPageEnd = page?.contextPageEnd as String + } + root.config.sortBys.sortBy.each { sortBy -> + sortBys.add(new Expando(id: new Integer(sortBy.id as String), name: sortBy.display as String, expression: sortBy + .expression as String, defaultSortBy: sortBy.defaultSortBy)) + } - /** - * Get next facets from database - * @param domainId - * @return - */ - @Transactional(isolation=Isolation.READ_UNCOMMITTED) - Expando getUIConfig(docType, domainId, selectedFacetsMap, q, locale){ + //no expando + relevancy = root.config.page.relevancy.field.each { field -> + relevancy.add(field) + } + hitlistDoc = root.config.page.hitlist - Expando uiConfig = new Expando() - def selectedFacetsXml - try { - List domainFacets = [] - List selectedFacets = [] - List nextFacets = [] - List renderers = [] - def relevancy = [] - def hitlistDoc + uiConfig.with { + domainFacets = this.domainFacets + selectedFacets = this.selectedFacets + nextFacets = this.nextFacets + renderers = this.renderers + sortBys = this.sortBys + hitlistDoc = this.hitlistDoc + relevancy = this.relevancy + } + } + } - /* create xml to sent to sp to get next facets */ - selectedFacetsXml = createSelectedFacetXml(selectedFacetsMap) - def sortBys = [] - log.debug "[$domainId, $selectedFacetsXml, $docType, $q]" + } catch (Exception exception) { + log.error exception.printStackTrace() + throw new RuntimeException("Exception while calling spSolrConfiguration with parameters domainId=${domainId}, " + + "selectedFacetsXml=${selectedFacetsXml}, docType=${docType}, q=${q}. Exception message=" + exception.message) + } + uiConfig + } - log.debug (selectedFacetsXml) - def nextFacetXml - sql.query("{call spSolrConfiguration(@domainId=?, @selectedFacets=?, @docType=?, @q=?, @locale= ?)}", [domainId, selectedFacetsXml, docType, q, locale]) { rs -> - while(rs.next()){ - nextFacetXml = rs.getString(1) - log.debug nextFacetXml - } - if(nextFacetXml) { - def root = new XmlSlurper().parseText(nextFacetXml) + Object createDomainFacet(domainFacet) { + new Expando(abbr: domainFacet.abbr as String + , description: domainFacet?.descr as String + , displayName: domainFacet?.displayName as String + , isMultiSelect: domainFacet?.isMultiSelect as String + , valueBooleanOperator: domainFacet?.valueBooleanOperator as String + , sequence: ((domainFacet?.sequence == '' ? -1 : domainFacet?.sequence) as String) as Integer + , resultSortOrder: domainFacet?.resultSortOrder as String + , resultListCount: ((domainFacet?.resultListCount == '' ? -1 : domainFacet?.resultListCount) as String) as Integer + ) + } - //domain facets - root.config.facets.domain.facet.each{ domainFacet-> - if(domainFacet.abbr =='ct') { - domainFacet.abbr = 'ct1' - domainFacets.add(createDomainFacet(domainFacet)) - domainFacet.abbr = 'ct2' - domainFacets.add(createDomainFacet(domainFacet)) - domainFacet.abbr = 'ct3' - domainFacets.add(createDomainFacet(domainFacet)) - domainFacet.abbr = 'ct4' - domainFacets.add(createDomainFacet(domainFacet)) - } else { - domainFacets.add(createDomainFacet(domainFacet)) - } + /** + * Get Next category facet based on current one. + * @param params + * @param nextFacets + * @return + */ + String createNextCategoryFCsQs(params, nextFacets) { + def nextCtUrl = '' + String nextCt = getNextCategory(params) + nextCtUrl = "&facet.field=${nextCt}_FC" + nextCtUrl + } - } - //selected facets - root.config.facets.selected.facet.each{ selectedFacet-> - selectedFacets.add(new Expando(abbr: selectedFacet.abbr as String - , valueId: selectedFacet?.valueId as String)) - } - //next facets - root.config.facets.next.facet.each{ facet-> - nextFacets.add(new Expando(abbr: facet.abbr as String)) - } - root.config.page.each{ page-> - renderers.add(page.renderer as String) - //add catalog /category page numbers - uiConfig.contextPageStart = page?.contextPageStart as String - uiConfig.contextPageEnd = page?.contextPageEnd as String - } - root.config.sortBys.sortBy.each{ sortBy-> - sortBys.add(new Expando(id:new Integer(sortBy.id as String), name:sortBy.display as String, expression:sortBy.expression as String, defaultSortBy: sortBy.defaultSortBy)) - } + String getNextCategory(params) { - //no expando - relevancy = root.config.page.relevancy.field.each{ field-> - relevancy.add(field) - } - hitlistDoc = root.config.page.hitlist + def nextCt = 'ct1' + if (params.ct3) { + nextCt = 'ct4' + } else if (params.ct2) { + nextCt = 'ct3' + } else if (params.ct1) { + nextCt = 'ct2' + } + nextCt + } + String createNextFitmentFCsQS(params) { + def fitmentFacetFieldsQuery = '' + def mk = params.mk + def md = params.md + def yr = params.yr + def pr = params.pr + Set fcs = [] - uiConfig.domainFacets = domainFacets - uiConfig.selectedFacets = selectedFacets - uiConfig.nextFacets = nextFacets - uiConfig.renderers = renderers - uiConfig.sortBys = sortBys - uiConfig.hitlistDoc = hitlistDoc - uiConfig.relevancy = relevancy - } - } + // Based on selected facets + if (mk && md && yr) { + fcs = ['mk', 'md', 'yr'] + } else if (mk && yr) { + fcs = ['mk', 'yr', 'mk_yr_md'] + } else if (md && yr) { + fcs = ['md', 'yr', 'mk_yr_md'] + } else if (mk && md) { + fcs = ['mk', 'md', 'mk_yr_md'] + } else if (yr) { + fcs = ['yr', 'yr_mk', 'yr_md'] + } else if (mk) { + fcs = ['mk', 'mk_yr', 'mk_md'] + } else { + fcs = ['mk', 'yr'] + } - } catch(Exception exception){ - log.error exception.printStackTrace() - throw new RuntimeException("Exception while calling spSolrConfiguration with parameters domainId=${domainId}, selectedFacetsXml=${selectedFacetsXml}, docType=${docType}, q=${q}. Exception message="+exception.message) - } - return uiConfig - } + if (pr) { + fcs += ['mk', 'md', 'yr'] + } - Object createDomainFacet(domainFacet) { - return new Expando(abbr: domainFacet.abbr as String - , description: domainFacet?.descr as String - , displayName: domainFacet?.displayName as String - , isMultiSelect: domainFacet?.isMultiSelect as String - , valueBooleanOperator: domainFacet?.valueBooleanOperator as String - , sequence: ((domainFacet?.sequence == '' ? -1 : domainFacet?.sequence) as String) as Integer - , resultSortOrder: domainFacet?.resultSortOrder as String - , resultListCount: ((domainFacet?.resultListCount =='' ?-1 : domainFacet?.resultListCount ) as String) as Integer - ) - } + fitmentFacetFieldsQuery = fcs.collect { item -> "&facet.field=${item}_FC" }.join('') - /** - * Get Next category facet based on current one. - * @param params - * @param nextFacets - * @return - */ - String createNextCategoryFCsQs(params, nextFacets){ - def nextCtUrl ='' - String nextCt = getNextCategory(params) - nextCtUrl ="&facet.field=${nextCt}_FC" - return nextCtUrl - } + fitmentFacetFieldsQuery + } - String getNextCategory(params){ + /** + * Create selected and next facet query string. + * It adds next category facet. + * It also removes 'ct' and 'av' from next facets and av* from selected facets. + * @param params + * @param selectedFacets + * @param nextFacets + * @return + */ + String createSelectedAndNextFCsQS(params, selectedFacets, nextFacets) { - def nextCt = "ct1" - if(params.ct3){ - nextCt = "ct4" - } else if (params.ct2){ - nextCt = "ct3" - } else if (params.ct1){ - nextCt = "ct2" - } - return nextCt - } - String createNextFitmentFCsQS(params){ - def fitmentFacetFieldsQuery = '' - def mk = params.mk - def md = params.md - def yr = params.yr - def pr = params.pr - Set fcs = [] + def facetFieldsQuery = '&facet=true&facet.mincount=1&facet.limit=-1&facet.field=dm_ci_ct1_ct2_ct3_ct4_pr' - // Based on selected facets - if (mk && md && yr){ - fcs = ['mk', 'md', 'yr'] - } else if (mk && yr) { - fcs = ['mk', 'yr', 'mk_yr_md'] - } else if (md && yr) { - fcs = ['md', 'yr', 'mk_yr_md'] - } else if (mk && md) { - fcs = ['mk', 'md', 'mk_yr_md'] - } else if (yr) { - fcs = ['yr', 'yr_mk', 'yr_md'] - } else if (mk) { - fcs = ['mk', 'mk_yr', 'mk_md'] - } else { - fcs = ['mk', 'yr'] - } + // Request for next category facets based on previous one + String categoryFacetFieldsQuery = createNextCategoryFCsQs(params, nextFacets) - if (pr) { - fcs += ['mk', 'md', 'yr'] - } + // Get next fitments + String fitmentFacetFieldsQuery = createNextFitmentFCsQS(params) - fitmentFacetFieldsQuery = fcs.collect{item -> "&facet.field=${item}_FC"}.join('') + facetFieldsQuery += (categoryFacetFieldsQuery + fitmentFacetFieldsQuery) - return fitmentFacetFieldsQuery - } + //Add both requested and next facets in facet list + def facetsToRequest = [] + //leave av in the nextFacets to get av_FC. Just remove ct. Also the fitment related FCs. + nextFacets.each { nextFacet -> + def nextFacetAbbr = nextFacet.abbr + if (nextFacetAbbr == 'ct' || nextFacetAbbr == 'mk' || nextFacetAbbr == 'md' || nextFacetAbbr == 'yr') { + return + } + facetsToRequest.add(nextFacetAbbr) + } + selectedFacets.each { selectedFacet -> + //skip av100 like fictitious facets + if ((selectedFacet.startsWith('av') && selectedFacet.length() > 2) || selectedFacet == 'dm') { + return + } + facetsToRequest.add(selectedFacet) + } - /** - * Create selected and next facet query string. - * It adds next category facet. - * It also removes 'ct' and 'av' from next facets and av* from selected facets. - * @param params - * @param selectedFacets - * @param nextFacets - * @return - */ - String createSelectedAndNextFCsQS(params, selectedFacets, nextFacets){ + facetsToRequest.each { + facetToRequest -> facetFieldsQuery += "&facet.field=${facetToRequest}_FC" + } + facetFieldsQuery + } - def facetFieldsQuery = '&facet=true&facet.mincount=1&facet.limit=-1&facet.field=dm_ci_ct1_ct2_ct3_ct4_pr' + /** + * Note page end is not used right now - it will be used if range search is enabled.. + * @param pn + * @param pageEnd + * @param core + * @return + */ + String createPageNumberFQ(ci, pn, pageEnd, core) { - // Request for next category facets based on previous one - String categoryFacetFieldsQuery = createNextCategoryFCsQs(params, nextFacets) - - // Get next fitments - String fitmentFacetFieldsQuery = createNextFitmentFCsQS(params) - - facetFieldsQuery += (categoryFacetFieldsQuery + fitmentFacetFieldsQuery) - - //Add both requested and next facets in facet list - def facetsToRequest = [] - //leave av in the nextFacets to get av_FC. Just remove ct. Also the fitment related FCs. - nextFacets.each{nextFacet -> - def nextFacetAbbr = nextFacet.abbr - if(nextFacetAbbr == 'ct' || nextFacetAbbr == 'mk' || nextFacetAbbr == 'md' || nextFacetAbbr == 'yr' ){ - return - } - facetsToRequest.add(nextFacetAbbr) - } - selectedFacets.each { selectedFacet -> - //skip av100 like fictitious facets - if((selectedFacet.startsWith('av') && selectedFacet.length() > 2) || selectedFacet == 'dm'){ - return - } - facetsToRequest.add(selectedFacet) - } - - facetsToRequest.each{ - facetToRequest-> facetFieldsQuery+="&facet.field=${facetToRequest}_FC" - } - - return facetFieldsQuery - } - - /** - * Note page end is not used right now - it will be used if range search is enabled.. - * @param pn - * @param pageEnd - * @param core - * @return - */ - String createPageNumberFQ (ci, pn, pageEnd, core) { - - def fqTerm = '' - if (pn || pageEnd) { - //always search page number in selected catalog - def fieldName = 'pn_FC' - // def pageStart = pn?:pageEnd - //pageEnd = pageEnd?:pageStart + def fqTerm = '' + if (pn || pageEnd) { + //always search page number in selected catalog + def fieldName = 'pn_FC' + // def pageStart = pn?:pageEnd + //pageEnd = pageEnd?:pageStart // switch (core) { // case 'part': // fieldName = "productPageNumber" @@ -535,30 +548,30 @@ // fieldName = "pageNumber" // break; // } - fqTerm = "$fieldName:${ci}|${pn}" - } - return fqTerm + fqTerm = "$fieldName:${ci}|${pn}" + } + fqTerm - } + } - /** - * Function to escape the special characters with \ for regex support - * @param s - * @return - */ - public String escapeQueryChars(String s) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - // These characters are part of the query syntax and must be escaped - if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' - || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~' - || c == '*' || c == '?' || c == '|' || c == '&' || c == ';' || c == '/' - || Character.isWhitespace(c)) { - sb.append('\\'); - } - sb.append(c); - } - return sb.toString(); - } -} \ No newline at end of file + /** + * Function to escape the special characters with \ for regex support + * @param s + * @return + */ + String escapeQueryChars(String s) { + StringBuilder sb = new StringBuilder() + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i) + // These characters are part of the query syntax and must be escaped + if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' + || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~' + || c == '*' || c == '?' || c == '|' || c == '&' || c == ';' || c == '/' + || Character.isWhitespace(c)) { + sb.append('\\') + } + sb.append(c) + } + sb.toString() + } +} Index: branches/pssGrails3/src/main/groovy/com/lemanscorp/search/solr/QuickSearch.groovy =================================================================== diff -u -r8885 -r8886 --- branches/pssGrails3/src/main/groovy/com/lemanscorp/search/solr/QuickSearch.groovy (.../QuickSearch.groovy) (revision 8885) +++ branches/pssGrails3/src/main/groovy/com/lemanscorp/search/solr/QuickSearch.groovy (.../QuickSearch.groovy) (revision 8886) @@ -38,5 +38,3 @@ class QuickSearchResponse { List divisions = [] } - -