我们正在努力将Solr 3.6集成到电子商务网站。我们已将数据编入索引搜索表现非常好。
我们在如何使用Predictive Search / Auto Complete Search建议方面遇到一些困难。也有兴趣了解实现此功能的最佳实践。
我们的目标是提供类似于http://www.amazon.com/的预测搜索,但不知道如何使用Solr实现它。更具体地说,我想了解如何从Solr构建这些术语,还是由solr外部的其他东西管理?如何建立字典以提供这些建议?此外,对于某些领域,搜索应提供类别搜索。尝试在亚马逊搜索框中输入“xper”,你会注意到除了xperia,xperia s,xperia p之外,它还列出了手机和手机中的xperia s。配件,这是一个类别。
使用自定义词典时,这很难管理。或者我们可能不知道如何正确地做到这一点。期待您指导我们如何最好地利用solr来实现这种暗示搜索。
答案 0 :(得分:7)
我建议你写一些博文:
答案 1 :(得分:1)
我使用了Highlight方法,因为facet.prefix对于大索引而言太重了,而其他的文档很少或不清楚(我是一个愚蠢的程序员)
因此,我们假设用户刚刚输入了“aaa bbb ccc
”
我们的自动完成功能(java / javascript)将使用以下参数调用solr
q="aaa bbb"~100 ...base query, all the typed words except the last
fq=ccc* ...suggest word filter using last typed word
hl=true
hl.q=ccc* ...highlight word will be the one to suggest
fl=NONE ...return empty docs in result tag
hl.pre=### ...escape chars to locate highlight word in the response
hl.post=### ...see above
您还可以使用“rows
”和“hl.fragsize
”参数控制建议的数量
每个文档中的突出显示单词将是“aaa bbb
”字符串
更多建议词是高亮词之前/之后的词,当然,你可以实现更多过滤器来提取有效词,避免重复,限制建议
如果有兴趣我可以给你发一些例子......
已编辑:有关该方法的更多详情
我给出的示例部分假设jquery给出的'autocomplete'机制:我们在Web应用程序中调用jsp(或servlet)作为请求参数传递'q'用户输入的单词。
这是jsp的代码
ByteArrayInputStream is=null; // Used to manage Solr response
try{
StringBuffer queryUrl=new StringBuffer('putHereTheUrlOfSolrServer');
queryUrl.append("/select?wt=xml");
String typedWords=request.getParameter("q");
String base="";
if(typedWords.indexOf(" ")<=0) {
// No space typed by user: the 'easy case'
queryUrl.append("&q=text:");
queryUrl.append(URLEncoder.encode(typedWords+"*", "UTF-8"));
queryUrl.append("&hl.q=text:"+URLEncoder.encode(typedWords+"*", "UTF-8"));
} else {
// Space chars present
// we split the search in base phrase and last typed word
base=typedWords.substring(0,typedWords.lastIndexOf(" "));
queryUrl.append("&q=text:");
if(base.indexOf(" ")>0)
queryUrl.append("\""+URLEncoder.encode(base, "UTF-8")+"\"~1000");
else
queryUrl.append(URLEncoder.encode(base, "UTF-8"));
typedWords=typedWords.substring(typedWords.lastIndexOf(" ")+1);
queryUrl.append("&fq=text:"+URLEncoder.encode(typedWords+"*", "UTF-8"));
queryUrl.append("&hl.q=text:"+URLEncoder.encode(typedWords+"*", "UTF-8"));
}
// The additional parameters to control the solr response
queryUrl.append("&rows="+suggestPageSize); // Number of results returned, a parameter to control the number of suggestions
queryUrl.append("&fl=A_FIELD_NAME_THAT_DOES_NOT_EXIST"); // Interested only in highlights section, Solr return a 'light' answer
queryUrl.append("&start=0"); // Use only first page of results
queryUrl.append("&hl=true"); // Enable highlights feature
queryUrl.append("&hl.simple.pre=***"); // Use *** as 'highlight border'
queryUrl.append("&hl.simple.post=***"); // Use *** as 'highlight border'
queryUrl.append("&hl.fragsize="+suggestFragSize); // Another parameter to control the number of suggestions
queryUrl.append("&hl.fl=content,title"); // Look for result only in some fields
queryUrl.append("&facet=false"); // Disable facets
/* Omitted section: use a new URL(queryUrl.toString()) to get the solr response inside a byte array */
is=new ByteArrayInputStream(solrResponseByteArray);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(is);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//response/lst[@name=\"highlighting\"]/lst/arr[@name=\"content\"]/str");
NodeList valueList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
Vector<String> suggestions=new Vector<String>();
for (int j = 0; j < valueList.getLength(); ++j) {
Element value = (Element) valueList.item(j);
String[] result=value.getTextContent().split("\\*\\*\\*");
for(int k=0;k<result.length;k++){
String suggestedWord=result[k].toLowerCase();
if((k%2)!=0){
//Highlighted words management
if(suggestedWord.length()>=suggestedWord.length() && !suggestions.contains(suggestedWord))
suggestions.add(suggestedWord);
}else{
/* Words before/after highlighted words
we can put these words inside another vector
and use them if not enough suggestions */
}
}
}
/* Finally we build a Json Answer to be managed by our jquery function */
out.print(request.getParameter("json.wrf")+"({ \"suggestions\" : [");
boolean firstSugg=true;
for(String suggestionW:suggestions) {
out.print((firstSugg?" ":" ,"));
out.print("{ \"suggest\" : \"");
if(base.length()>0) {
out.print(base);
out.print(" ");
}
out.print(suggestionW+"\" }");
firstSugg=false;
}
out.print(" ]})");
}catch (Exception x) {
System.err.println("Exception during main process: " + x);
x.printStackTrace();
}finally{
//Gracefully close streams//
try{is.close();}catch(Exception x){;}
}
希望有所帮助, NIK
答案 2 :(得分:0)
这可能会帮助你。我正在努力做到这一点。