开场白:
我看过几本书说关于lucene中的BooleanQuery查询条件的参数
Boolean.Clause.MUST,Boolean.Clause.MUST_NOT,Boolean.Clause.SHOULD之关的关系,其实就好象是集合中的交集并集等关系.这里不重复书的例子,说一点我平时在工作中的应用吧.
书基本都是说,当MUST与SHOULD关联使用的时候,跟MUST使用是一样的,那天我做一个关系搜索结果按相关排序,这里简单说一下需求,这是说用户输入关键字后,应该把所有的付费会员商品按相关度从高到低排序来推荐给用户.现在已经一批付费会员的编号了,同时知道会员用户的产品名称与产品介绍。那应该如何去按照输入的关键字来排序呢?要知道,关键字有可能与付费会员的产品完全不相关,当然,这些不相关产品会排在最后边。
现在贴出相关的代码
package com.lucene.test;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopFieldDocs;
/**
*
* @author kernaling.wong
* 本类只是演示should对结果的出现是没有影响的,但是影响结果的相关度,可以利用之来进度某些相关的排序搜索
*/
public class LuceneTest {
private static String INDEX_PATH = "./Index/";
public static void main(String[] args) {
if(false){ //做索引的时候就把 true;
IndexWriter writer = null;
try{
writer = new IndexWriter(INDEX_PATH,new StandardAnalyzer(),MaxFieldLength.LIMITED);
Document doc = new Document();
Field fieldCode = new Field("Code","1",Field.Store.YES,Field.Index.ANALYZED);
Field fieldName = new Field("Name","电热炉",Field.Store.YES,Field.Index.ANALYZED);
Field fieldInfo = new Field("Info","这是一个电热
炉",Field.Store.YES,Field.Index.ANALYZED);
doc.add(fieldCode);
doc.add(fieldName);
doc.add(fieldInfo);
writer.addDocument(doc);
doc = new Document();
fieldCode = new Field("Code","2",Field.Store.YES,Field.Index.ANALYZED);
fieldName = new Field("Name","电水壶",Field.Store.YES,Field.Index.ANALYZED);
fieldInfo = new Field("Info","解放牌电水壶",Field.Store.YES,Field.Index.ANALYZED);
doc.add(fieldCode);
doc.add(fieldName);
doc.add(fieldInfo);
writer.addDocument(doc);
doc = new Document();
fieldCode = new Field("Code","3",Field.Store.YES,Field.Index.ANALYZED);
fieldName = new Field("Name","水杯",Field.Store.YES,Field.Index.ANALYZED);
fieldInfo = new Field("Info","钢化水杯",Field.Store.YES,Field.Index.ANALYZED);
doc.add(fieldCode);
doc.add(fieldName);
doc.add(fieldInfo);
writer.addDocument(doc);
doc = new Document();
fieldCode = new Field("Code","4",Field.Store.YES,Field.Index.ANALYZED);
fieldName = new Field("Name","碟子",Field.Store.YES,Field.Index.ANALYZED);
fieldInfo = new Field("Info","质量很好",Field.Store.YES,Field.Index.ANALYZED);
doc.add(fieldCode);
doc.add(fieldName);
doc.add(fieldInfo);
writer.addDocument(doc);
System.out.println("索引建立完成!");
}catch(Exception ex){
ex.printStackTrace();
}finally{
if(writer != null){
try{
writer.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}else{
IndexSearcher search = null;
IndexReader ir = null;
try{
search = new IndexSearcher(INDEX_PATH);
String keyword = "水"; //用户输入了需要搜索的关键字
BooleanQuery bq = new BooleanQuery();
/**
* 以下上查询条件,因为无论用户输入的关键字如何都需要全部显示付费会员商品,相关度从高
到低
*/
BooleanQuery tmpBQ = new BooleanQuery(); //这是一个
tmpBQ.add(new TermQuery((new Term("Code","1"))),BooleanClause.Occur.MUST);
tmpBQ.add(new TermQuery((new Term("Name",keyword))),BooleanClause.Occur.SHOULD);
tmpBQ.add(new TermQuery((new Term("Info",keyword))),BooleanClause.Occur.SHOULD);
bq.add(tmpBQ,BooleanClause.Occur.SHOULD);
tmpBQ = new BooleanQuery();
tmpBQ.add(new TermQuery((new Term("Code","2"))),BooleanClause.Occur.MUST);
tmpBQ.add(new TermQuery((new Term("Name",keyword))),BooleanClause.Occur.SHOULD);
tmpBQ.add(new TermQuery((new Term("Info",keyword))),BooleanClause.Occur.SHOULD);
bq.add(tmpBQ,BooleanClause.Occur.SHOULD);
tmpBQ = new BooleanQuery();
tmpBQ.add(new TermQuery((new Term("Code","3"))),BooleanClause.Occur.MUST);
tmpBQ.add(new TermQuery((new Term("Name",keyword))),BooleanClause.Occur.SHOULD);
tmpBQ.add(new TermQuery((new Term("Info",keyword))),BooleanClause.Occur.SHOULD);
bq.add(tmpBQ,BooleanClause.Occur.SHOULD);
tmpBQ = new BooleanQuery();
tmpBQ.add(new TermQuery((new Term("Code","4"))),BooleanClause.Occur.MUST);
tmpBQ.add(new TermQuery((new Term("Name",keyword))),BooleanClause.Occur.SHOULD);
tmpBQ.add(new TermQuery((new Term("Info",keyword))),BooleanClause.Occur.SHOULD);
bq.add(tmpBQ,BooleanClause.Occur.SHOULD);
Sort sort = new Sort(SortField.FIELD_SCORE); //按相关度来排序
TopFieldDocs tdocs = search.search(bq,null,4,sort);
ScoreDoc scoreDocs[] = tdocs.scoreDocs;
ir = search.getIndexReader();
for(int i=0;i<scoreDocs.length;i++){
Document tmpDoc = ir.document(scoreDocs[i].doc);
System.out.println("文档得分:"+scoreDocs[i].score+"\t产品编号:"+tmpDoc.get
("Code")+"\t产品名称:"+tmpDoc.get("Name")+"\t产品说明:"+tmpDoc.get("Info"));
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
try{
if(search != null){
search.close();
}
if(ir != null){
ir.close();
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
}
测试环境是 windowsXP + jdk1.6 与 lucene2.4.
实现后排序的结果应该是这样
后记
以上那种方面需要说明的是,如果出现了大量的付费会员的时候,即,需要BooleanClause.Occur.SHOULD很多用户编号的时候,建议不要再用些方法了,同时BooleanQuery条件中会限制BooleanQuery.add的条件数量,默认是1024个,当然也可以手动设置它的最大上限,通过setMaxClauseCount(int maxCount),因为按我以上那种方法,当注册用户数很多,比如10W或者以上的时候,搜索时性能就会成为瓶颈了。这个时候,我现在想出的方法就是更改Lucene索引的字段,不要再指定付费用户去SHOULD每一个付费用户了,改为增加一个字段去表示是否注册用户.然后再用上边类似方法就可以比较高效率地实现这个功能了,最原先那个种方法是头脑发热的时候想出来的,那时付费的用户并不多,所以就算这样实现起来都没有问题,不过现在也已经改为到第二种方法了,在暂时无法改变lucene源代码实现与算法的时候,那只能改变自己的方法了.
- 大小: 37.8 KB
分享到:
相关推荐
第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。 第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。 public void add(Query query, BooleanClause.Occur occur) BooleanClause...
例如,可以创建两个`Query`对象,一个用于匹配关键词,另一个用于时间范围,然后通过`BooleanClause.Occur`设置操作符(如SHOULD、MUST或MUST_NOT),将它们组合成一个布尔查询。 **类似MySQL的LIKE条件**在Lucene...
如果一个子句是MUST,另一个是MUST_NOT,则结果中不会包含MUST_NOT子句对应的文档。SHOULD子句则代表可选条件,多个SHOULD子句之间是逻辑或的关系,它们的组合结果是所有子句的并集。在实际编程中,这些概念可以通过...
示例代码展示了如何构建两个关键词`word1`和`word2`至少出现在`name`字段或`body`字段中的一个查询。 ```java TermQuery query1 = new TermQuery(new Term("name", "word1")); TermQuery query2 = new TermQuery(new...
在创建索引之前,首先需要创建一个 `IndexWriter` 对象。这一步骤涉及到目录(Directory)的选择以及分词器(Analyzer)的设置: - **选择目录**:通过 `FSDirectory.open(new File(indexPath));` 指定索引存储的...
Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发。它提供了高级文本检索功能,广泛用于构建搜索引擎和其他需要高效全文检索能力的应用。本文将重点介绍 Lucene 2.4 版本的基本概念和使用方法,帮助...
Lucene是一个高性能、全文本搜索库,而Elasticsearch则是在Lucene的基础上构建的一个分布式、RESTful风格的搜索和数据分析引擎。两者在面试中常常被提及,以下是对这两个技术的关键知识点的深入解析。 首先,Lucene...
Lucene是一个开源的全文检索引擎工具包,它提供了创建索引、执行高效搜索以及排序结果的能力。在Lucene中,Score树是用于计算文档相关性得分的关键结构,从而决定搜索结果的排序。 ### 一、`IndexSearcher.search...
Elasticsearch是一个基于Lucene的搜索服务器,提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。它是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于...
Apache Lucene 是一个高度可扩展的全文检索库,它为开发者提供了一套强大的搜索引擎功能,以便在各种应用程序中实现复杂的全文搜索。Lucene 不是一个独立的搜索引擎产品,而是需要开发者将其集成到自己的系统中,以...
例如,`new BooleanQuery.Builder().Add(query1, Occur.MUST).Add(query2, Occur.SHOULD).Build()`将创建一个必须包含query1且可以包含query2的查询。 2. **短语查询**:通过`PhraseQuery`,可以查找精确的短语匹配...
在上面的代码中,我们使用 BoolQuery 构建了一个复杂的搜索条件,包括 must、mustNot、should 方法。 FilteredQuery FilteredQuery 是一种特殊的搜索方式,允许开发者使用过滤条件来限制搜索结果。例如,以下代码...
安装PM > Install-Package LrNet.Lucene.Fluent 首先,在使用查询构建器之前,您需要在项目中的某处指定: QueryBuilder . Version = /* Lucene Version you want to use */QueryBuilder . DefaultAnalyzer = /* ...
例如,查询只需要满足“标题包含 Elasticsearch”或者“作者不是 John Doe”中的任意一个条件即可。 3. **NOT**:表示指定的子查询必须排除在外。例如,查询结果中不能出现“作者是 John Doe”的记录。 4. **FILTER*...
在Laravel框架中,Elasticsearch(简称ES)是一个常用的数据搜索引擎,特别是在处理大量数据时,它的性能和灵活性使得开发者倾向于使用它替代传统的数据库。`ELSQueryBuilderTrait`是为简化在Laravel应用中与Elastic...
- **节点和集群**:ElasticSearch 支持在多台服务器上部署,形成一个集群。每个服务器上的 ElasticSearch 实例称为一个节点。 - **分片(Shard)**:当单个节点的计算能力和硬件限制不足以应对大量数据时,可以将...
Elasticsearch是一个强大的分布式搜索引擎,基于Lucene库构建。在Java API中,与Elasticsearch交互,特别是进行搜索操作,主要是通过使用`QueryBuilder`对象来构造JSON格式的查询条件。本篇文章将深入探讨如何利用...
集群中有一个主节点负责协调集群状态和其他节点的工作负载分配。 2. **创建集群**: 首先安装 Elasticsearch,然后配置集群名称、网络设置等,启动多个节点并使其加入同一个集群。 3. **查询集群健康**: 使用 `_...
这样可以确保在任意一个节点故障时,数据仍能被其他节点接管,保持服务的连续性。 **三、Elasticsearch的查询参数优化** 1. **Lucene的打分模型** Elasticsearch基于Lucene的TF-IDF评分模型来决定搜索结果的...