实现功能
最基础的搜索功能就是包含连续的搜索框中的值,这个可以用mysql的LIKE很容易实现。但是更高级的模糊搜索应该是可以不连续的包含并且有一定的容错率。
我的搜索功能分为按照标题搜索和按照主题搜索,并且搜索结果可以根据发布时间或热度排序。另外,我实现了一个相似度的功能,即搜索结果和搜索内容的相似度,100%即为搜索框的所有内容都要包含才能被搜索到,0%则可以搜索到全部的图片。比如,我输入park,相似度调为50%,那么只要包含p和a或p和r或p和k或a和r或a和k或r和k,即可。
思路
其实这就是组合数的种类,设搜索内容长度为m,相似度为s,则抽取的字母的长度n=m*s,那么就有C(m,n)种结果。
采用递归思想,从m个字母里取n个只需先取第i(0<i<m-n+2)个,再从i+1到m中去n-1个,直到n=1。
代码
public List<Picture> getPicturesByFuzzyContent(String content,String filter,String sort,int page, int pageSize,int similar){
//去掉空格
content = content.replaceAll(" +","");
//高级模糊
List<String> contents = fuzzyString(content,similar);
StringBuilder sql = new StringBuilder("SELECT i.ImageID id, i.Title title, i.PATH path, u.UserName author FROM travelimage i, " +
"traveluser u WHERE i.UID = u.UID AND (i.");
if(filter.equals("title")){
sql.append("Title LIKE '");
sql.append(contents.get(0));
sql.append("' ");
int i = 1;
while (i < contents.size()){
sql.append("OR i.Title LIKE '");
sql.append(contents.get(i));
sql.append("' ");
i++;
}
}
else{
sql.append("Content LIKE '");
sql.append(contents.get(0));
sql.append("' ");
int i = 1;
while (i < contents.size()){
sql.append("OR i.Content LIKE '");
sql.append(contents.get(i));
sql.append("' ");
i++;
}
}
sql.append(") ");
sql.append("ORDER BY ");
if(sort.equals("hot")){
sql.append("i.Hot ");
}
else {
sql.append("i.RecentUpdate ");
}
sql.append("DESC LIMIT ?,?");
// System.out.println(sql);
return getAll(sql.toString(),(page - 1)*pageSize,pageSize);
}
private List<String> fuzzyString(String initString,int similar){
List<String> stringList = new ArrayList<>();
int length = (int)Math.ceil(similar*initString.length()/100.0) ;
if(length==0){
stringList.add("%");
}
else {
// System.out.println(length);
charsCombinationWithLabel(new StringBuilder("%"),stringList,new StringBuilder(initString),length,1,0);
}
return stringList;
}
private void charsCombinationWithLabel(StringBuilder readyString, List<String> stringList, StringBuilder leftString, int needNumber,int lengthOfReady,int begin){
if(readyString.length() <= lengthOfReady+1){
readyString.append("%%");//占位
}
if(needNumber == 1){
for(int i = begin; i < leftString.length();i++){
readyString.setCharAt(lengthOfReady,leftString.charAt(i));
readyString.setCharAt(lengthOfReady+1,'%');
stringList.add(String.valueOf(readyString));
}
}
else {
for(int i = begin;i < leftString.length();i++){
char toDelete = leftString.charAt(i);
readyString.setCharAt(lengthOfReady,toDelete);
readyString.setCharAt(lengthOfReady+1,'%');
charsCombinationWithLabel(readyString,stringList,leftString,needNumber-1,lengthOfReady+2,i+1);
}
}
}