Subversion Repositories SmartDukaan

Rev

Rev 517 | Rev 545 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/**
 * 
 */
package in.shop2020.serving.services;


import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;


import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import org.apache.commons.lang.StringUtils;

/**
 * @author naveen
 *
 */
public class SolrSearchService {
        /**
         * 
         */
        private static Log log = LogFactory.getLog(SolrSearchService.class);
        
        private static final int NUMBER_OF_ROWS = 20, PERCENTAGE_OF_TOTAL_RESULTS = 2;
        /**
         * 
         */
        public static String SOLR_URL = "http://localhost:8983/solr/select/";
        
        /**
         * 
         */
        private XPath xpath;
        
        /**
         * 
         */
        private InputSource inputSource;
        
        private String minPrice = "0";
        
        private String maxPrice = "*";
        
        TreeMap<String,HashMap<String,Integer>> facetMap;
        
        HashMap<String, String[]> resultMap;
        /**
         * 
         * @param query
         * @param facetDefinitionIDs
         */
        public SolrSearchService(String query, String[] facetqueries,   String[] facetDefinitionIDs) {
                
                this.xpath = XPathFactory.newInstance().newXPath();
                String uri = SOLR_URL + "?wt=xml&q=" + query;
                
                /*
                if(facetqueries.containsKey("minPrice")){
                        this.minPrice = facetqueries.get("minPrice");
                }else {
                        this.minPrice = "0";
                }
                if(facetqueries.containsKey("maxPrice")){
                        this.maxPrice = facetqueries.get("minPrice"); 
                }else {
                        this.maxPrice = "*";
                }
                facetqueries.remove("minPrice");
                facetqueries.remove("maxPrice");
                */
                
                // query for price filtering
                //uri += "&facet.query=F_50002:[" + minPrice + " TO " + maxPrice + "]";
                // get stats for price field
                uri += "&stats=on&stats.field=F_50002";
//               
//              if(facetqueries.containsKey("maxPrice")){
//                       if(facetqueries.containsKey("minPrice")){
//                               uri += "&fq=price:["+facetqueries.get("minPrice")+" TO "+ facetqueries.get("maxPrice")+"]";
//                       }else {
//                               uri += "&fq=price:[0 TO "+ facetqueries.get("minPrice")+"]";
//                       }
//                               
//              }
                                 
//              for(String facetParam : facetqueries.keySet()){
//                              uri += "&fq=" + facetParam + ":" + facetqueries.get(facetParam);
//              }

                
                if(facetqueries != null) {
                        for(int i=0; i<facetqueries.length; i++) {

                                if(facetqueries[i].contains(" ") && !facetqueries[i].contains("F_50002")){
                                        String[] tokens = facetqueries[i].split(":");
                                        uri += "&fq=" + tokens[0] + "\"" + tokens[1] + "\"";
                                }else{
                                        uri += "&fq=" + facetqueries[i] + "";
                                }
                        }
                }
                uri += "&fl=ID,Name&facet=true&rows=" + NUMBER_OF_ROWS;
                
                for(int i=0; i<facetDefinitionIDs.length; i++) {
                        uri += "&facet.field=" + facetDefinitionIDs[i];
                }
                log.info("uri=" + uri);
                
                this.inputSource = new InputSource(uri);
                this.facetMap = new TreeMap<String, HashMap<String,Integer>>(getFacetMap());
        }
        
        public static void main(String[] args){
                /*
        // Hard coded for now
        String[] facetDefIDs = new String[] {"F_50001", "F_50002", "F_50003", "F_50004", "F_50005", "F_50006", "F_50007", "F_50008", "F_50009"};

        // Hard-coded for now
        String[] facetLabels = new String[] {
                "Brand", "Price","Form Factor", "Carry In Pocket", "Cellular Technologies", 
                "Data Connectivity", "Camera Resolution", "Built-in Memory", 
                "Talk time"
        };

                 */
        String[] facetDefIDs = new String[] {"Category","F_50002","F_50001",  "F_50006", "F_50007" };
        String[] facetLabels = new String[] {"Category","Price", "Brand", "Data Connectivity", "Camera Resolution"      };

        
        String[] fqrys = {};
                SolrSearchService search = new SolrSearchService("nokia", fqrys, facetDefIDs);
        
        long[] entityIDs = search.getResultEntityIDs();
        log.info("entityIDs=" + Arrays.toString(entityIDs));
        
        String[] entityNames = search.getResultEntityNames();
        log.info("entityNames=" + Arrays.toString(entityNames));
        search.getFacetMap();
        
        search.getResultMap();
        search.getRangeQueryResultMap();
        search.getPriceStatsMap();
        
        for (int i=0; i<facetDefIDs.length; i++) {
                search.getFacetCounts(facetDefIDs[i]);
                search.getFacetValues(facetDefIDs[i]);
        }
        
        }

        
        public TreeMap<String,HashMap<String,Integer>> removeUnwantedFacets(TreeMap<String,HashMap<String,Integer>> facetMap, int numberOfResults){
                TreeMap<String,HashMap<String,Integer>> tempFacets = new TreeMap<String, HashMap<String,Integer>>(facetMap); 
                for(String facet : facetMap.keySet()){
                        if(facetMap.get(facet).size() <= 1){
                                // FIXME  
                                tempFacets.remove(facet);
                        }else{
                                int sumOfFacetCounts = 0;
                                for(String facetValueName : facetMap.get(facet).keySet()){
                                        if(facetMap.get(facet).get(facetValueName) == 0 || facetMap.get(facet).get(facetValueName) == numberOfResults){
                                                tempFacets.get(facet).remove(facetValueName);
                                                // FIXME
                                                /*
                                                HashMap<String, Integer> tmp = tempFacets.get(facet);
                                                tmp.remove(facetValueName);
                                                tempFacets.put(facet, tmp);
                                                */
                                        }else{
                                                sumOfFacetCounts += facetMap.get(facet).get(facetValueName);
                                        }
                                }
                                if(sumOfFacetCounts < numberOfResults*PERCENTAGE_OF_TOTAL_RESULTS/100){
                                        tempFacets.remove(facet);
                                }
                        }
                }

                return tempFacets;
        }
        
        public HashMap<String,Integer> getFacetDetails(String facetName){
                return facetMap.get(facetName);
        }
        
        public TreeMap<String,HashMap<String,Integer>> getFacetMap() {
                facetMap = new TreeMap<String,HashMap<String,Integer>>();
                
                String facetNamePath = "/response/lst/lst[@name = 'facet_fields']/lst";
                String facetValuePath = "/response/lst/lst[@name = 'facet_fields']/lst/int/@name";
                String facetCountPath = "/response/lst/lst[@name = 'facet_fields']/lst/int";
                //expression += "lst[@name = 'F_"+ facetDefinitionID +"']/int/@name";
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(facetNamePath, this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                NodeList subNodes = null;
                String facetName = new String();
                
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        facetName = node.getAttributes().getNamedItem("name").getNodeValue();
                        
//                      System.out.println("facetName   :  "  + node.getAttributes().getNamedItem("name").getNodeValue());
                        
                        subNodes = node.getChildNodes();
                        HashMap<String,Integer> facetValueCountMap = new HashMap<String,Integer>();
                        for(int j=0; j<subNodes.getLength(); j++) {
                                Node subNode = subNodes.item(j);
                                if(Integer.parseInt(subNode.getTextContent())==0)
                                                continue;
                                facetValueCountMap.put(subNode.getAttributes().getNamedItem("name").getNodeValue(), Integer.parseInt(subNode.getTextContent()));
        //                      System.out.println("facetValue   :  " + subNode.getTextContent()  +  ":"+  subNode.getAttributes().getNamedItem("name").getNodeValue());
                        }
                        //System.out.println(facetName +":"+ facetValueCountMap);
                        facetMap.put(facetName, facetValueCountMap);
                        }
                System.out.println(facetMap);
                
                int numberOfResults = 10;
                
                facetMap = removeUnwantedFacets(facetMap, numberOfResults);
                System.out.println(facetMap);
                return facetMap;
                }
        
        public HashMap<String, String[]> getResultMap() {
                resultMap = new HashMap<String, String[]>();

                String resultDocsPath = "/response/result/doc";
                
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(resultDocsPath, this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                

                
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        String docID = node.getFirstChild().getTextContent();
                        String[] values = new String[] {node.getFirstChild().getNextSibling().getTextContent()};
                        resultMap.put(docID, values);   
                }
                System.out.println("resultMap is " + resultMap);
                return resultMap;
        }

        public HashMap<String, Double> getPriceStatsMap() {
                HashMap<String, Double> priceStatsMap = new HashMap<String, Double>();

                String resultDocsPath = "/response/lst[@name = 'stats']/lst[@name = 'stats_fields']/lst[@name = 'F_50002']";
                
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(resultDocsPath, this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                NodeList subNodes = nodes.item(0).getChildNodes();
                
                for(int i=0; i<subNodes.getLength(); i++) {
                        Node node = subNodes.item(i);
                        
                        String parameter = node.getAttributes().getNamedItem("name").getNodeValue();
                        String value = node.getTextContent();
                        priceStatsMap.put(parameter, Double.parseDouble(value));        
                }
                System.out.println("priceStatsMap is " + priceStatsMap);
                return priceStatsMap;
        }

        public HashMap<String,Integer> getRangeQueryResultMap() {
                HashMap<String, Integer> rangeQueryResultMap = new HashMap<String,Integer>();

                String resultDocsPath = "/response/lst[@name = 'facet_counts']/lst[@name = 'facet_queries']/int";
                
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(resultDocsPath, this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);

                        String query = node.getAttributes().getNamedItem("name").getNodeValue();
                        String docCount = node.getTextContent();

                        rangeQueryResultMap.put(query,Integer.parseInt(docCount));      
                }
                System.out.println("rangeQueryResultMap is " + rangeQueryResultMap);
                return rangeQueryResultMap;
                
        }

                /**
         * 
         * @return
         */
        public long[] getResultEntityIDs() {
                String expression = "/response/result/doc/long";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, this.inputSource,
                                        XPathConstants.NODESET);
                } 
                catch(XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                long[] values = new long[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        String value = node.getTextContent();
                        values[i] = Long.parseLong(value);
                }
                
                return values;
        }
        
        /**
         * 
         * @return
         */
        public String[] getResultCategoryNames() {
                String expression = "/response/lst/lst[@name = 'facet_fields']/";
                expression += "lst[@name = 'Category']/int/@name";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, 
                                this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                String[] values = new String[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        values[i] = node.getTextContent();
                }
                
                return values;
        }
        
        /**
         * 
         * @return
         */
        public int[] getResultCategoryCounts() {
                String expression = "/response/lst/lst[@name = 'facet_fields']/";
                expression += "lst[@name = 'Category']/int";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, 
                                this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                int[] values = new int[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        values[i] = Integer.parseInt(node.getTextContent());
                }
                
                return values;
        }
        
        /**
         * 
         * @return
         */
        public String[]  getResultEntityNames() {
                String expression = "/response/result/doc/str";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, this.inputSource,
                                        XPathConstants.NODESET);
                } 
                catch(XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                String[] values = new String[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        String value = node.getTextContent();
                        values[i] = value;
                }
                
                return values;
        }

        /**
         * 
         * @param facetDefinitionID
         * @return
         */
        public String[] getFacetValues(String facetDefinitionID) {
                String expression = "/response/lst/lst[@name = 'facet_fields']/";
                expression += "lst[@name = '"+ facetDefinitionID +"']/int/@name";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, 
                                this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                String[] values = new String[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        values[i] = node.getTextContent();
                        //log.info("Facets Values  " + values[i]);
                }
                
                return values;
        }
        
        /**
         * 
         * @param facetDefinitionID
         * @return
         */
        public String[] getFacetCounts(String facetDefinitionID) {
                String expression = "/response/lst/lst[@name = 'facet_fields']/";
                expression += "lst[@name = '" + facetDefinitionID + "']/int";
                
                NodeList nodes = null;
                try {
                        nodes = (NodeList) this.xpath.evaluate(expression, 
                                this.inputSource, XPathConstants.NODESET);
                }
                catch (XPathExpressionException xpee) {
                        return null;
                }
                
                if(nodes.getLength() == 0) {
                        return null;
                }
                
                String[] values = new String[nodes.getLength()];
                for(int i=0; i<nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        values[i] = node.getTextContent();
//                      log.info("Facets Counts  " + values[i]);
                }
                
                return values;
        }
}