您的位置:首页 > 科技 > IT业 > 工作纪实56-ES搜索串一致性

工作纪实56-ES搜索串一致性

2024/10/10 15:11:04 来源:https://blog.csdn.net/u013553309/article/details/141417772  浏览:    关键词:工作纪实56-ES搜索串一致性

最近接收到了一个需求,一个用户有一组搜索串,比如字符串:abcdefg,如果新增的数据是abdcdfge,则视为是同一条数据,可以理解为即使顺序不同,但是实际上也是唯一串;
为什么是一个数据串我解释一下:大部分的公司es搜索功能(中台),都是会做二次开发的,到实际业务部门,需要根据他们二次开发的规则,提供一个查询数据串

思路

  • 对即将生成的唯一串数据,要先处理成有序字段【treeMap】
  • 生成的唯一串结果最好是定长(不定长的字符串->定长的字符串:hash算法)
  • 运算效率(暂时不考虑,一般都很快)

有点数字签名的意思,只不过这个地方不需要公司秘钥

代码

我选择的是sha-256哈希加密,安全性还可以,生成的效率够用

如果不考虑安全性的话,md5效率要更好一点;

public static String genUniqueKey(String uid, String queryCond) {String[] paramsArray = queryCond.split("&");Map<String, String> paramsMap = new TreeMap<>();for (String param : paramsArray) {String[] keyValue = param.split("=");paramsMap.put(keyValue[0], keyValue[1]);}// 将参数按照键名排序StringBuilder sortedParams = new StringBuilder(uid).append("&");for (Map.Entry<String, String> entry : paramsMap.entrySet()) {sortedParams.append(entry.getKey()).append("=").append(entry.getValue()).append("&");}// 使用SHA-256生成哈希值try {java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");byte[] hash = md.digest(sortedParams.toString().getBytes("UTF-8"));StringBuilder hexString = new StringBuilder();for (byte b : hash) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) hexString.append('0');hexString.append(hex);}return hexString.toString();} catch (Exception e) {e.printStackTrace();}return null;
}

思考

sha-256生成的串太长了,想短点?
这个算法输出的结果是64(32 * 2)个字符,一个字符2个字节(sha-256生成的结果是32位的)
策略1: 截断处理
直接截断或者自定义抽取不同位置的字符,形成新的串,数据量不大的情况下,理论上唯一性也可以保证

策略2:套娃算法

  1. 考虑过压缩算法(一般在网络传输的时候传输、接收用,不符合场景)
  2. 使用其他的定长算法二次加密【没找到】
  3. 自定义算法,一定范围内的定长【转载自:https://developer.aliyun.com/article/816907,见仁见智吧,如果每个字符串都不一样,长度直接翻倍了】
    第一种,只统计字符出现次数,比如aabcccccaaa,压缩成a5b1c5
public static String doDepressTwo(String str) {if ("".equals(str)) return str;char[] chars = str.toCharArray();HashMap<Character, Integer> map = new HashMap<>();for (char c : chars) {if (map.containsKey(c)) {//如果存在该键,则只需要value+1Integer integer = map.get(c);map.put(c, ++integer);} else {//如果不存在该键,就直接放入,value为1map.put(c, 1);}}StringBuilder sb = new StringBuilder();map.entrySet().forEach(entry -> {//将key和value拼接到sbsb.append(entry.getKey()).append(entry.getValue());});return sb.toString();
}

第二种,统计相邻字符串出现次数,比如aabcccccaaa,压缩成a2b1c5a3
思路:需要维护一个当前对比字符,一个字符出现次数,用第n个字符去和第n+1个字符对比,相等则出现次数+1,不相等则拼接在字符串后面

public static String doDepress(String str) {//字符串为空直接返回if ("".equals(str)) return str;StringBuilder buffer = new StringBuilder();//用第n个字符去和第n+1个字符对比char c = str.charAt(0);//记录字符出现次数,默认为1int repeat = 1;for (int i = 1; i < str.length(); i++) {if (c == str.charAt(i)) {//如果第n个字符和第n+1个字符相等,则出现次数+1repeat++;} else {//如果第n个字符和第n+1个字符不相等,则拼接在字符串后面buffer.append(c).append(repeat);//拼接完后重置当前字符串c = str.charAt(i);//重置字符出现次数repeat = 1;}}//最后一组在for循环里是没有拼接的return buffer.append(c).append(repeat).toString();
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com