JAVA关系表达式解析微引擎
生活随笔
收集整理的這篇文章主要介紹了
JAVA关系表达式解析微引擎
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
為什么80%的碼農(nóng)都做不了架構師?>>> ??
背景介紹:
為什么需要這個表達式解析微引擎?
? ? ?首先這個引擎是產(chǎn)生于調用鏈路跟蹤系統(tǒng),我們知道在調用跟蹤系統(tǒng)里經(jīng)常會根據(jù)關鍵字搜索日志但有時候我們搜一個關鍵字可能搜出N條記錄這時我們就需要有表達式了需要更精準搜索,比如搜 既包含 'a' 又包含 'b' 再排除 'c'? 等類似這樣。
? ? ?那一般的做法可能就是前端搞一個動態(tài)表單,然后用戶去選擇類型(and、or、not),這樣就需要前端修改了。重點來了,有沒有一種方式前端不修改后端服務去解析用戶輸出的搜索詞匯重而得出我們想要的表達式呢?
? ? ?請往下看
解析引擎源碼:
public class Keyword {private String key;private RelationEnum relation;public Keyword(String key,RelationEnum relation) {this.key = key;this.relation = relation;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public RelationEnum getRelation() {return relation;}public void setRelation(RelationEnum relation) {this.relation = relation;}}public enum LabelEnum {AND(new Character('&'),RelationEnum.AND),OR(new Character('|'),RelationEnum.OR),BLANK(new Character(' '),RelationEnum.OR),EXCLAMATION(new Character('!'),RelationEnum.NO);private Character label;private RelationEnum relation;LabelEnum(Character label,RelationEnum relation) {this.label = label;this.relation = relation;}public Character getLabel() {return label;}public void setLabel(Character label) {this.label = label;}public RelationEnum getRelation() {return relation;}public void setRelation(RelationEnum relation) {this.relation = relation;} }public enum RelationEnum {AND,OR,NO }public class SquareBracket {private LinkedList<Integer> left = Lists.newLinkedList();private LinkedList<Integer> right = Lists.newLinkedList();public void addLeft(int index) {this.left.add(index);}public void addRight(int index) {this.right.add(index);}public LinkedList<Integer> getLeft() {return left;}public LinkedList<Integer> getRight() {return right;}}public enum TagStatusEnum {VALID,UNCONFIRMED,INVALID }public class Tag {private int index;private LabelEnum label;private TagStatusEnum status;public Tag(LabelEnum label,int index,TagStatusEnum labelStatusEnum) {this.label = label;this.index = index;this.status = labelStatusEnum;}public LabelEnum getLabel() {return label;}public void setLabel(LabelEnum label) {this.label = label;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}public TagStatusEnum getStatus() {return status;}public void setStatus(TagStatusEnum status) {this.status = status;}}public class ExpressionProcessor {private static final char PREFIX_BRACKET = '[';private static final char SUFFIX_BRACKET = ']';/*** 分詞keyword,并解析相應關系* 具體參考:{@linkplain com.huize.framework.apm.data.es.expression.LabelEnum} </br>* 如果表達式的特殊字段需要查詢則需要用 ‘[]’括起則有效,且在同一組中,只有最外層的有效;</br>* * <pre>* ExpressionProcessor.split("12&34") = (12,&)、(34,&)* ExpressionProcessor.split("12!34") = (12,&)、(34,!)* ExpressionProcessor.split("12[!]34") = (12!34,&)* ExpressionProcessor.split("12[[!34]]") = (12[!34],&)* </pre>*/public static List<Keyword> split(String keyword) {return convert(keyword,mark(keyword));}private static Pair<List<Tag>,List<SquareBracket>> mark(String keyword) {List<Tag> tags = Lists.newArrayList();TagStatusEnum status = TagStatusEnum.VALID;int unconfirmedCount = 0;Tag tag = null;List<SquareBracket> squareBrackets = Lists.newArrayList();SquareBracket squareBracket = new SquareBracket();squareBrackets.add(squareBracket);for (int i = 0; i < keyword.length(); i++) {final char ch = keyword.charAt(i);if(ch == PREFIX_BRACKET) {if(unconfirmedCount == 0) {squareBracket = new SquareBracket();squareBrackets.add(squareBracket);}squareBracket.addLeft(i);unconfirmedCount += 1;status = TagStatusEnum.UNCONFIRMED;continue;}if(ch == SUFFIX_BRACKET) {unconfirmedCount -=1;if(status == TagStatusEnum.UNCONFIRMED) {resetTagStatus(tags);}if(unconfirmedCount == 0) {status = TagStatusEnum.VALID;}squareBracket.addRight(i);continue;}tag = getTag(ch,i,status);if(i == 0 && tag== null) {tag = new Tag(LabelEnum.AND, -1, TagStatusEnum.VALID);}if(tag != null) {tags.add(tag);}}return Pair.of(tags, squareBrackets);}private static List<Keyword> convert(String keyword,Pair<List<Tag>,List<SquareBracket>> pair) {List<Tag> tags = pair.getLeft();if(CollectionUtils.isEmpty(tags)) {Lists.newArrayList(new Keyword(keyword,RelationEnum.AND));}List<Keyword> keywords = Lists.newArrayListWithCapacity(tags.size()); List<Integer> bracketIndexs = getValidBracketIndexs(pair.getRight());final int size = tags.size();int step = 0;int next = 0;for(int i = 0; i < size; i++) {Tag tag = tags.get(i);if(tag == null) {continue;}if(TagStatusEnum.INVALID == tag.getStatus()) {continue;}next = i + 1;int index = tag.getIndex();step = index;if (next < size) {while(TagStatusEnum.INVALID == tags.get(next).getStatus() && next < (size -1)) {next += 1;}if(TagStatusEnum.INVALID == tags.get(next).getStatus()) {step = keyword.length();}else {step = tags.get(next).getIndex();}}else {step = keyword.length();}if(step - index > 1) {keywords.add(new Keyword(cut(keyword,index+1,step,bracketIndexs),tag.getLabel().getRelation()));}}return keywords;}private static String cut(String keyword,int start,int end,List<Integer> bracketIndexs) {List<Integer> list = Lists.newArrayList();for(Integer index : bracketIndexs) {if(index >=start && index <= end) {list.add(index);}}StringBuffer buffer = new StringBuffer(StringUtils.substring(keyword,start,end));if(!CollectionUtils.isEmpty(list)) {int delCount = 0;for(int index : list) {int delIndex = index - delCount- start;char ch = buffer.charAt(delIndex);if(ch == PREFIX_BRACKET || ch == SUFFIX_BRACKET) {buffer.deleteCharAt(delIndex);delCount += 1;}}}return buffer.toString();}private static void resetTagStatus(List<Tag> tags) {if(!CollectionUtils.isEmpty(tags)) {for(Tag tag : tags) {if(TagStatusEnum.UNCONFIRMED == tag.getStatus()) {tag.setStatus(TagStatusEnum.INVALID);}}}}private static Tag getTag(char charset,int index,TagStatusEnum status) {LabelEnum label = null;if(LabelEnum.AND.getLabel() == charset) {label = LabelEnum.AND;}else if(LabelEnum.OR.getLabel() == charset) {label = LabelEnum.OR;}else if(LabelEnum.BLANK.getLabel() == charset) {label = LabelEnum.BLANK;}else if(LabelEnum.EXCLAMATION.getLabel() == charset) {label = LabelEnum.EXCLAMATION;}if(label != null) {return new Tag(label,index,status);}return null;}private static List<Integer> getValidBracketIndexs(List<SquareBracket> squareBrackets) {List<Integer> bracketIndexs = Lists.newArrayList();if(CollectionUtils.isEmpty(squareBrackets)) {return bracketIndexs;}for(SquareBracket squareBracket : squareBrackets) {if(CollectionUtils.isEmpty(squareBracket.getLeft()) || CollectionUtils.isEmpty(squareBracket.getRight())) {continue;}int first = squareBracket.getLeft().getFirst();int last = squareBracket.getRight().getLast();if(last > first) {bracketIndexs.add(first);bracketIndexs.add(last);}}return bracketIndexs;}}代碼就上面這么多,非常簡潔。
下面就來測試下:
public class ExpressionProcessorTest {public static void main(String[] args) {String keyword = "a&d!c";//String keyword = "20180209002149[!]27343565";//String keyword = "20180209002149[!&!]27343565";//String keyword = "201802||09002149[!&!]27343565&&sdfas";//String keyword = "測試]][[!]測試[[[[psdf]23541345!@#$%^|)(*";//String keyword = "201802|||09002149[!&!]27343565&&sdfas";//String keyword = "201802|||!!09002149[!&!]27343565&&sdfas";//String keyword = "201802||!!09002149[!&!]27343565&&sdfas";System.out.println(JsonUtils.beanToJson(ExpressionProcessor.split(keyword)));}}運行:
[{"key":"a","relation":"AND"},{"key":"d","relation":"AND"},{"key":"c","relation":"NO"}]
轉載于:https://my.oschina.net/woter/blog/1843812
總結
以上是生活随笔為你收集整理的JAVA关系表达式解析微引擎的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人工智能学习体系大纲(src:http:
- 下一篇: sysbench 压测 详解