1. 程式人生 > >Solr搜尋的基本工具類

Solr搜尋的基本工具類

package com.yi.solr.util;

import com.eunke.constant.Auth;
import com.eunke.solr.bean.SolrVehicle;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.javatuples.Pair;
import org.javatuples.Triplet;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SolrQueryUtil {
	
	public static final int COMMIT_TIMES = -1;
	
	public static final int COMMIT_DELAY_TIMES = 60000;
	
	/**
	 * 用於查詢條件拼接時,是否加入條件,該值不加過濾
	 */
	public static final int INVALID = -1;

	/**
	 *
	 */
	public static final int TRUE = 1;

	public static final int FALSE = 0;
	
	/**
	 * 用於不查詢任何結果
	 */
	public static final int NORESULT = -2;
	
	public static final String QUERY_ALL = "*:*";
	
	public static final int DIRECTION_VALID = -1;
	public static final int DIRECTION_ONE = 0;
	
	public static final int DIRECTION_TWO = 1;

	/**
	 *  直轄市code的特別對映關係
	 */
	private final static Map<Long, Long> locactionCodeMap = new HashMap<>();

	//直轄市code的特別對映關係,如果是市級直轄市,轉成省級直轄市
	static {
		locactionCodeMap.put(1010100000l, 1010000000l);
		locactionCodeMap.put(1020100000l, 1020000000l);
		locactionCodeMap.put(1090100000l, 1090000000l);
		locactionCodeMap.put(1220100000l, 1220000000l);
	}


	/**
	 *  直轄市code的特別對映關係,如果是省級直轄市,轉成市級直轄市
	 */
	private final static Map<Long, Long> zhiXiaShiCodeMap = new HashMap<>();
	//直轄市code的特別對映關係
	static {
		zhiXiaShiCodeMap.put(1010000000l, 1010100000l);
		zhiXiaShiCodeMap.put(1020000000l, 1020100000l);
		zhiXiaShiCodeMap.put(1090000000l, 1090100000l);
		zhiXiaShiCodeMap.put(1220000000l, 1220100000l);
	}

	/**
	 * 是否為直轄市
	 * @param code
	 * @return
	 */
	public static boolean isZhiXiaShi(Long code){
		return locactionCodeMap.containsKey(code)	;
	}

	/**
	 * 地域code特別處理,如果是市級直轄市,轉成省級直轄市
	 * @param code
	 * @return
	 */
	public static Long zhiXiaShiCodeProcess(Long code){
		if(zhiXiaShiCodeMap.containsKey(code)){
			return zhiXiaShiCodeMap.get(code);
		}
		return code;
	}

	/**
	 * 地域code特別處理,如果是市級直轄市,轉成省級直轄市
	 * @param code
	 * @return
	 */
	public static Long locationCodeProcess(Long code){
		if(locactionCodeMap.containsKey(code)){
			return locactionCodeMap.get(code);
		}
		return code;
	}

	public static String getPolygonQueryStr(SolrPolygon polygon, String fildName){
		StringBuilder sb = new StringBuilder();
		if(polygon != null){
			polygon.transformPolygon();
			sb.append(fildName + ":\"IsWithin(POLYGON((");
			sb.append(polygon.getLeftTop().getLongitude() + " " + polygon.getLeftTop().getLatitude() + ",");
			sb.append(polygon.getRightTop().getLongitude() + " " + polygon.getRightTop().getLatitude() + ",");
			sb.append(polygon.getRightBootom().getLongitude() + " " + polygon.getRightBootom().getLatitude() + ",");
			sb.append(polygon.getLeftBootom().getLongitude() + " " + polygon.getLeftBootom().getLatitude() + ",");
			sb.append(polygon.getLeftTop().getLongitude() + " " + polygon.getLeftTop().getLatitude());
			sb.append("))) distErrPct=");
			sb.append(polygon.getDistErrPct());
			sb.append("\"");
		}
		return  sb.toString();
	}
	
	public static String getLatLonQueryStr(double latitude, double longitude, double distance, String fildName){
		return "{!geofilt score=distance pt=" + latitude + "," + longitude + " sfield=" + fildName + " d=" + distance + "}";
	}
	
	public static void generateLatLonQuery(double latitude, double longitude, double distance, String fildName, SolrQuery solrQuery){
		solrQuery.addFilterQuery("{!geofilt}");
		solrQuery.add("spatial", "true");
		solrQuery.add("sfield", fildName);
		solrQuery.add("pt", latitude + "," + longitude);
		solrQuery.add("d", distance + "");
	}
	
	public static String getTimeQuery(String fieldName, Date start, Date end){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");  
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
		StringBuilder sb = new StringBuilder();
		sb.append(fieldName + ":[");
		if(start != null){
			sb.append(sdf.format(start));
		}else{
			sb.append("*");
		}
		sb.append(" TO ");
		if(end != null){
			sb.append(sdf.format(end));
		}else{
			sb.append("*");
		}
		sb.append("]");
		return sb.toString();
	}
	
	public static int getVehicleScore(SolrVehicle vehicle){
		int i = 0;
		if (vehicle.getLicenseAuth() != null && vehicle.getLicenseAuth() == Auth.AUTH_OK.getIntValue()) {
            i = i | (1 << 0);
        } else {
            i = i & (0xFFFFFFFF ^ (1 << 0));
        }
		
        if (StringUtils.isNotBlank(vehicle.getImg())) {
            i = i | (1 << 1);
        } else {
            i = i & (0xFFFFFFFF ^ (1 << 1));
        }
        
        if (StringUtils.isNotBlank(vehicle.getDriverName())) {
            i = i | (1 << 2);
        } else {
            i = i & (0xFFFFFFFF ^ (1 << 2));
        }
        
        if (vehicle.getNumberAuth() != null && vehicle.getNumberAuth() == Auth.AUTH_OK.getIntValue()) {
            i = i | (1 << 3);
        } else {
            i = i & (0xFFFFFFFF ^ (1 << 3));
        }
        
        if (vehicle.getDriverAuth() != null && vehicle.getDriverAuth() == Auth.AUTH_OK.getIntValue()) {
            i = i | (1 << 4);
        } else {
            i = i & (0xFFFFFFFF ^ (1 << 4));
        }
		return i;
	}
	
	public static String repairAddress(String address){
		if(StringUtils.isNoneBlank(address)){
			return address.replaceAll("壯族自治區+$", "").replaceAll("回族自治區+$", "").replaceAll("維吾爾自治區+$", "").replaceAll("自治區+$", "")
					.replaceAll("特別行政區+$", "").replaceAll("新區+$", "").replaceAll("省+$", "").replaceAll("市+$", "").replaceAll("縣+$", "")
					.replaceAll("鎮+$", "").replaceAll("區+$", "");
		}else{
			return address;
		}
	}

	public static void addPoiRangeOld(String fieldName, long poiCode, SolrQuery solrQuery) {
		String poiCodeStr = poiCode + "";
		poiCodeStr = poiCodeStr.replaceAll("0+$", "");
		int size = 10 - poiCodeStr.length();
		for(int i = 0; i <  size; i++){
			poiCodeStr += "9";
		}
		solrQuery.addFilterQuery(fieldName + ":[" + poiCode + " TO " + poiCodeStr + "]");
	}



	//code最後的索引位置
	private static final int CODE_END_INDEX = 10;
	//鎮在code中的開始索引
	private static final int TOWN_BEGIN_INDEX = 7;
	//縣在code中的開始索引
	private static final int COUNTY_BEGIN_INDEX = 5;
	//市在code中的開始索引
	private static final int CITY_BEGIN_INDEX = 3;
	//省在code中的開始索引
	private static final int PROVINCE_BEGIN_INDEX = 1;
	//國家在code中的開始索引
	private static final int COUNTRY_BEGIN_INDEX = 0;


	/**
	 * code 生成規則:
	 * 比如為1010118001,code一共分為5個部分
	 *
	 *    0     1              3     5          7
	 * 	 國家	省(直轄市)   市    縣(區)		鎮(村)
	 * 	  1		01			   01    18      	001
	 * @param fieldName
	 * @param poiCode
	 * @param solrQuery
	 */

	private static final List<Triplet<Integer, Integer, Integer>> indexList = new ArrayList<Triplet<Integer, Integer, Integer>>();

	static {
		indexList.add(new Triplet<>(TOWN_BEGIN_INDEX, CODE_END_INDEX, CODE_END_INDEX));
		indexList.add(new Triplet(COUNTY_BEGIN_INDEX, TOWN_BEGIN_INDEX, TOWN_BEGIN_INDEX));
		indexList.add(new Triplet(CITY_BEGIN_INDEX, COUNTY_BEGIN_INDEX, COUNTY_BEGIN_INDEX));
		indexList.add(new Triplet(PROVINCE_BEGIN_INDEX, CITY_BEGIN_INDEX, CITY_BEGIN_INDEX));
		indexList.add(new Triplet(COUNTRY_BEGIN_INDEX, PROVINCE_BEGIN_INDEX, PROVINCE_BEGIN_INDEX));
	}

	public static void addPoiRange(String fieldName, long poiCode, SolrQuery solrQuery) {


		Pair<String, String> poiRange = getPoiRange(poiCode);

		//補齊10位
		String beginCode = poiRange.getValue0();
		String endCode = poiRange.getValue1();
		solrQuery.addFilterQuery(fieldName + ":[" + beginCode + " TO " + endCode + "]");
	}

	/**
	 * 獲取solr 地域code範圍
	 * @param poiCode
	 * @return
	 */
	public static Pair<String, String> getPoiRange(long poiCode) {
		String poiCodeStr = poiCode + "";
		String prefix = "1";
		for(Triplet<Integer, Integer, Integer> index : indexList){
			String str = poiCodeStr.substring(index.getValue0(), index.getValue1());
			if(NumberUtils.toInt(str, 0) > 0){
				prefix = poiCodeStr.substring(0, index.getValue2());
				break;
			}
		}

		//補齊10位
		String beginCode = (prefix+"000000000").substring(0, CODE_END_INDEX);
		String endCode = (prefix+"999999999").substring(0, CODE_END_INDEX);
		return Pair.with(beginCode , endCode);
	}

	public static void addTopPoiRange(String fieldName, long poiCode, SolrQuery solrQuery) {
	    if(poiCode == SolrConstant.CHINA_LOC_CODE){
	        addPoiRange(fieldName, poiCode, solrQuery);
	    }else{
	        String poiCodeStr = poiCode + "";
	        poiCodeStr = poiCodeStr.replaceAll("0+$", "");
	        int len = poiCodeStr.length();
	        if(len % 2 == 0){
	            poiCodeStr = poiCodeStr.substring(0, len-1);
	        }else {
	            poiCodeStr = poiCodeStr.substring(0, len-2);
	        }
	        String poiCodeStr2 = poiCodeStr;
	        int size = 10 - poiCodeStr.length();
	        for(int i = 0; i <  size; i++){
	            poiCodeStr += "9";
	            poiCodeStr2 += "0";
	        }
	        solrQuery.addFilterQuery(fieldName + ":[" + poiCodeStr2 + " TO " + poiCodeStr + "]");
	    }
    }

	public static String filterAddress(String address){
		if (StringUtils.isNotBlank(address)) {
			address = address.replaceAll(SolrConstant.QUAN_GUO, "").replaceAll(SolrConstant.QUAN_JIN, "");
			address = address.trim();
		}
		return address;
	}

	/**
	 * 單值OR匹配
	 * @param objects
	 * @return
	 */
	public static String getSingleOrMatch(Object[] objects){
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (int i = 0; i < objects.length; i++) {
			if (i == 0) {
				sb.append(objects[i]);
			} else {
				sb.append(" OR " + objects[i] + "");
			}
		}
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 單值NOT匹配
	 * @param objects
	 * @return
	 */
	public static String getSingleNotMatch(Object[] objects){
		StringBuilder sb = new StringBuilder();
		sb.append("(*");
		for (int i = 0; i < objects.length; i++) {
			sb.append(" NOT " + objects[i] + "");
		}
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 單值OR匹配字串
	 * @param objects
	 * @return
	 */
	public static String getSingleOrMatchString(Object[] objects){
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (int i = 0; i < objects.length; i++) {
			if (i == 0) {
				sb.append("\""+objects[i]+"\"");
			} else {
				sb.append(" OR \"" + objects[i] + "\"");
			}
		}
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 單值OR匹配
	 * @param nums
	 * @return
	 */
	public static String getSingleOrMatch(int[] nums){
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (int i = 0; i < nums.length; i++) {
			if (i == 0) {
				sb.append(nums[i]);
			} else {
				sb.append(" OR " + nums[i] + "");
			}
		}
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 獲取範圍OR匹配
	 * @param ranges
	 * @return
	 */
	public static String getRangeOrMatch(String[] ranges){
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (int i = 0; i < ranges.length; i++) {
			String[] array = ranges[i].split(SolrConstant.SECTION_SYMBOL);
			String temp = "[" + array[0] + " TO " + array[1] + "]";
			if (i == 0) {
				sb.append(temp);
			} else {
				sb.append(" OR " + temp + "");
			}
		}
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 地域code範圍匹配
	 * @param codes
	 * @return
	 */
	public static String getCodeRangeMatch(Long[] codes){
		StringBuilder fq = new StringBuilder();
		if(codes != null && codes.length > 0){
			for (int i = 0; i < codes.length; i++) {
				Pair<String, String> poiRange = SolrQueryUtil.getPoiRange(codes[i]);
				if (i == 0) {
					fq.append("[" + poiRange.getValue0() + " TO " + poiRange.getValue1() + "]");
				} else {
					fq.append(" OR [" + poiRange.getValue0() + " TO " + poiRange.getValue1() + "]");
				}
			}
		}
		return fq.toString();
	}

	/**
	 * 綜合OR匹配
	 * @param strings
	 * @return
	 */
	public static String getCompositeOrMatch(String[] strings){
		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (int i = 0; i < strings.length; i++) {
			String[] array = strings[i].split(SolrConstant.SECTION_SYMBOL);

			String temp = null;
			if(array != null && array.length == 1){
				temp = array[0];
			}else if(array != null && array.length == 2){
				temp = "[" + array[0] + " TO " + array[1] + "]";
			}

			if(StringUtils.isBlank(temp)){
				continue;
			}

			if (i == 0) {
				sb.append(temp);
			} else {
				sb.append(" OR " + temp + "");
			}
		}
		sb.append(")");
		return sb.toString();
	}


	/**
	 * 搜尋文字進行特殊字元轉義處理
	 * @param input
	 * @return
     */
	public static String transformSolrSpecialChar(String input){
		StringBuffer sb = new StringBuffer();
		String regex = "[+\\-&|!(){}\\[\\]^\"~*?:(\\) ]";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(input);
		while(matcher.find()){
			matcher.appendReplacement(sb, "\\\\"+matcher.group());
		}
		matcher.appendTail(sb);
		return sb.toString();
	}


	public static void main(String[] args) {
		System.out.println(transformSolrSpecialChar("yi wu"));
	}

}

包含常用的地點搜尋