Solr 使用自定义 Query Parser

2019-03-27 01:13|来源: 网路

原文出处:http://blog.chenlb.com/2010/08/solr-use-custom-query-parser.html

由于 Solr 默认的 Query Parser 生成的 Query 一般是 “短语查询”,导致只有很精确的结果才被搜索出来。大部分时候我们要分词后的 BooleanQuery。一年半前有篇关于 solr 使用自定义的 QueryParser 的文章。使用这个方法在 solr 中可以用自己的 Query Parser。

按照那篇文章,分别扩展:QParserPlugin、QParser、SolrQueryParser。我把它们实现为:ExtLuceneQParserPlugin、ExtLuceneQParser、SolrQueryParser 源码下载

配置使用,把 solr-1.4-query-parser-extand-0.1.jar 放到 solr.home/lib 里,同时也把 mmseg4j-all-1.8.2-with-dic.jar 放到 solr.home 当然也可以其它分词器(paoding 可以,看:solr 中使用 paoding 中文分词,N久前验证过 paoding 使用这个扩展可以,有问题通知我)。

schema.xml 加或改:

  1. <fieldType name="text_cn" class="solr.TextField" positionIncrementGap="100">  
  2.   <analyzer>  
  3.     <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory"/>  
  4.   </analyzer>  
  5. </fieldType>   
  6.   
  7. <!--  ..... -->  
  8.   
  9. <field name="title" type="text_cn" indexed="true" stored="true"/>  
  10.   
  11.  <defaultSearchField>title</defaultSearchField>  
  12.  <solrQueryParser defaultOperator="AND"/>  

保存 doc-demo.xml,

  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <add>  
  3. <doc>  
  4.   <field name="id">1</field>  
  5.   <field name="title">研究空格生命起源</field>  
  6. </doc>  
  7. </add>  

启动 solr (solr.root=e:/apache-solr-1.4.1), 提交一个文档。

  1. #启动 solr  
  2. cd solr.root/example  
  3. java -jar start.jar  
  4.   
  5. #提交索引  
  6. cd solr.root/example/exampledocs  
  7. java -jar post.jar doc-demo.xml  

用两种方式查询:

1、extand lucene query parser 方式:查 研究生命起源

结果:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <response>  
  3.   
  4. <lst name="responseHeader">  
  5.  <int name="status">0</int>  
  6.  <int name="QTime">0</int>  
  7.  <lst name="params">  
  8.   <str name="debugQuery">on</str>  
  9.   <str name="indent">on</str>  
  10.   <str name="q">研究生命起源</str>  
  11.   <str name="defType">extlucene</str>  
  12.  </lst>  
  13. </lst>  
  14. <result name="response" numFound="1" start="0">  
  15.  <doc>  
  16.   <str name="id">1</str>  
  17.   <str name="title">研究空格生命起源</str>  
  18.  </doc>  
  19. </result>  
  20. <lst name="debug">  
  21.  <str name="rawquerystring">研究生命起源</str>  
  22.  <str name="querystring">研究生命起源</str>  
  23.  <str name="parsedquery">+title:研究 +title:生命 +title:起源</str>  
  24.  <str name="parsedquery_toString">+title:研究 +title:生命 +title:起源</str>  
  25.  <str name="QParser">ExtLuceneQParser</str>  
  26. </lst>  
  27. </response>  

2、用 solr 的默认 query parser 的查询,查 研究生命起源

结果:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <response>  
  3.   
  4. <lst name="responseHeader">  
  5.  <int name="status">0</int>  
  6.  <int name="QTime">0</int>  
  7.  <lst name="params">  
  8.   <str name="debugQuery">on</str>  
  9.   <str name="indent">on</str>  
  10.   <str name="start">0</str>  
  11.   <str name="q">研究生命起源</str>  
  12.   <str name="version">2.2</str>  
  13.   <str name="rows">10</str>  
  14.  </lst>  
  15. </lst>  
  16. <result name="response" numFound="0" start="0"/>  
  17. <lst name="debug">  
  18.  <str name="rawquerystring">研究生命起源</str>  
  19.  <str name="querystring">研究生命起源</str>  
  20.  <str name="parsedquery">PhraseQuery(title:"研究 生命 起源")</str>  
  21.  <str name="parsedquery_toString">title:"研究 生命 起源"</str>  
  22.  <str name="QParser">LuceneQParser</str>  
  23. </lst>  
  24. </response>  

对比两个结果:

1、第一个是 debug 输出 QParser 为 ExtLuceneQParser,是刚才安装的扩展。并且可以搜索到内容,为 BooleanQuery("+title:研究 +title:生命 +title:起源");

2、第二个 debug 输出的 QParser 为 LuceneQParser,搜索不到内容,原因是它把查询解析为 PhraseQuery(title:"研究 生命 起源"),它们必须紧接着的(当然可以指定 slop)。

源码使用说明(在 readme.txt 里),源码下载

copy example 目录到 solr.root(e:/apache-solr-1.4.1) 里。

cd solr.root/example
java -jar start.jar

cd solr.root/example/exampledocs
java -jar post.jar doc-demo.xml

比较两链接:

http://localhost:8983/solr/select/?q=%E7%A0%94%E7%A9%B6%E7%94%9F%E5%91%BD%E8%B5%B7%E6%BA%90&defType=extlucene&indent=on&debugQuery=on
上面链接的参数可以加到 standard handle 里的defaults,如:

  1. <requestHandler name="standard" class="solr.SearchHandler" default="true">  
  2.   <!-- default values for query parameters -->  
  3.    <lst name="defaults">  
  4.      <str name="echoParams">explicit</str>  
  5.      <str name="defType">extlucene</str>  
  6.    </lst>  
  7. </requestHandler>  
  8.   
  9. <queryParser name="extlucene" class="com.chenlb.solr.search.ExtLuceneQParserPlugin"/>  

正常的 solr query parser
http://localhost:8983/solr/select/?q=%E7%A0%94%E7%A9%B6%E7%94%9F%E5%91%BD%E8%B5%B7%E6%BA%90&indent=on&debugQuery=on

这一问题困扰很多网友。特写这文章仅供参考。

lucene/solr 3.5 可以试试 solr-3.5-query-parser-extend.zip


转自:http://www.cnblogs.com/chenying99/archive/2012/07/24/2607243

相关问答

更多

Solr:使用Block Join Children Query Parser(Solr: Using the Block Join Children Query Parser)

看看你在这里再次提到的Solr Wiki。 请注意以下事项: The syntax for this parser is: q={!child of=<allParents>}<someParents>. The parameter allParents is a filter that matches only parent documents 在您的示例中,查询是{!child of="id:p1"}firstName:Bob 。 <allParents>使用的字段id ,但id包含在父文档和 ...

在Query Parser上禁用词干(Disable Stemming on Query Parser)

如果需要进行词干和非词干搜索,则需要在schema.xml为相同内容定义不同的字段,同时将文本索引到它们中(可能使用CopyField )。 一个领域应该有词干分析器而另一个领域不应该。 然后,您的搜索将指定要搜索的字段。 If you need to have stemmed and unstemmed searches, you'll need to define different fields in your schema.xml for the same content and simu ...

如何使单词与Solr一致?(How to make word concordance with Solr?)

您可以尝试使用hl.fragsize=100和hl.mergeContiguous=false并查看您获得了多少片段? (在solrconfig.xml中直接在SearchHandler中添加params之前,您可以通过在查询中指定所有参数来尝试各种选项。一旦找到一组您满意的参数,请在solrconfig中使用它们。) Can you try with hl.fragsize=100 and hl.mergeContiguous=false and see how many fragments y ...

Solr自定义排名(Solr custom ranking)

您可以应用boost函数(bf属性)以比简单查询术语提升更复杂的方式自定义您的评分。 这在DisMax查询解析器中可用,并且正如您所料,在Extended dismax查询解析器中进一步扩展 规范是您通常期望找到关于场长的信息,尽管它将与发现的任何场级增强相结合,并且您的逻辑(更长时间地权衡更长场)与默认值相反得分。 除非你创建一个自定义的相似性,否则这将使支持字段增强和逻辑变得困难。 顺便说一下,如果您决定采用该路线,则在索引时存储规范,而不是在查询时计算。 You can apply boos ...

自定义Solr组件插件中的查询构建(Query construction in custom Solr component plugin)

在prepare()方法中,就在你的外部API调用之前,你可以检查RequestBuilder.isDistrib() 。 对于即将分发的请求,此布尔值将为真。 然后,您可以使用此信息来确定您是否可以执行外部请求,或者您需要设置执行此作业的SolrCloud主机之一。 如何确定SolrCloud主机用于外部API? 你可以... 将主机之一连接到组件,并检查localhost是否是硬连线主机。 但是,这将不平衡主机负载。 有一个任意组件可以自行检查的任意度量,如主机1-10在当前分钟等于主机数量时 ...

Solr edismax Query Parser Operators(Solr edismax Query Parser Operators)

检查JIRA SOLR-1553的Edismax Parser。 它支持布尔运算符检查文档 supports queries such as AND, OR, NOT, -, and +. treats "and" and "or" as "AND" and "OR" in Lucene syntax mode. 对于AND ,运算符是+ , NOT -而OR不需要运算符。 Check the JIRA SOLR-1553 for the Edismax Parser. It does supp ...

Dismax solr查询解析器工作得很差(Dismax solr query parser working very poorly)

string字段仅匹配字段的确切值(表示大小写和空格等)。 为了实现您期望的那种匹配,您将需要一个文本字段。 示例模式中的text_general / text_en字段可能是可用的,至少作为起点,但您可能希望根据查询字段的方式精确调整字段的作用。 如果您没有同义词或者不想删除停用词,请删除这些行并仅保留tokenizer和小写过滤器: <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100"> ...

Lucene - JSON对象的自定义分析器/解析器?(Lucene - Custom Analyzer/Parser for JSON objects?)

如果您将始终搜索完整的值集... 为每个集创建“属性”字段。 该值只是连接的值集,即“1/2/2015:johndoe:2:text a:text b”。 或者......为每组创建单独的文档。 这将允许您搜索不同的值组合,而不会混淆不同的集合。 是的,这可能意味着重复文本字段。 如果它不大,那么我就不会太在意(特别是如果你没有使用“存储”字段)。 您是否需要在查询中组合文本和属性? (“text:ipsum AND property:xxx”) 如果没有,那么将文本放在另一个文档中。 如果想要搜 ...

Apache Solr:更像是这种自定义(Apache Solr: More Like This customization)

根据https://wiki.apache.org/solr/MoreLikeThisHandler,MoreLikeThisHandler支持CommonQueryParameters。 这意味着您应该能够在搜索中添加fq (过滤器查询)参数,并在f2之间过滤某些内容和其他内容。 例如: fq=f2:["2011-03-21" TO "2012-03-21"] 这说,找到MLT的所有结果,然后添加此过滤查询。 According to https://wiki.apache.org/solr/ ...

Solr:在solr查询响应中引入自定义字段(Solr: Introduce a custom field in solr query response)

您可以使用DocTransformer实现此目的。 只需从类继承并在transform方法中实现所需的逻辑: public void transform(SolrDocument doc, int docId) { String oldValue = doc.getFieldValue(fieldName); doc.put(newField,getNewValue(oldValue)); } You can achieve this using a DocTransformer ...