5

我们正在努力将 Solr 3.6 集成到电子商务网站。我们已经对数据进行了索引,并且搜索性能非常好。

我们在弄清楚如何使用预测搜索/自动完成搜索建议时遇到了一些困难。也有兴趣了解实现此功能的最佳实践。

我们的目标是提供类似于http://www.amazon.com/的预测搜索,但不知道如何使用 Solr 实现它。更具体地说,我想了解如何从 Solr 构建这些术语,还是由 solr 外部的其他东西管理?应该如何构建词典来提供这些建议?此外,对于某些领域,搜索应该提供类别搜索。尝试在亚马逊搜索框中输入“xper”,你会发现除了xperia、xperia s、xperia p,它还列出了手机和配件中的xperia s,这是一个类别。

使用自定义字典这将很难管理。或者我们可能不知道如何正确地做到这一点。期待您指导我们如何最好地利用 solr 来实现这种暗示性搜索。

4

3 回答 3

8

我建议你写几篇博文:

  • 这个向您展示了一个非常好的完整解决方案,该解决方案运行良好,但需要进行一些额外的工作,并为该特定目的使用特定的 lucene 索引(solr 核心)
于 2012-08-31T12:51:14.790 回答
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 给出的“自动完成”机制:我们在 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){;}
}

希望对您有所帮助,尼克

于 2015-10-28T18:36:12.823 回答
0

这可能会帮助你。我正在尝试做同样的事情。

http://solr.pl/en/2010/10/18/solr-and-autocomplete-part-1/

于 2014-10-30T12:16:26.093 回答