Solr搜尋的基本工具類
阿新 • • 發佈:2019-02-12
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")); } }
包含常用的地點搜尋