`
kernaling.wong
  • 浏览: 77833 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

我在工作中的Lucene中关于 MUST , SHOULD的一个想法

    博客分类:
  • java
阅读更多
开场白:
我看过几本书说关于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
1
1
分享到:
评论
4 楼 kernaling.wong 2015-05-18  
whz137458 写道
我觉得你思路有问题!(A&&B||C)||(D&&B||C)||(E&&B||C)
你就没想过(A||D||E)&&(B||C)

望指教~~
刚才我认真看了您的回复,其实呢,我那里的重点不在于哪个"或"哪个条件,我那里是测试例子,本来是通过一个 for 循环去拼成  (A&&B||C)||(D&&B||C)||(E&&B||C) 这样的条件,但后来为了测试例子方便才直接写了三个这样子的条件了.
当然您说的也有道理.
3 楼 whz137458 2015-04-09  
我觉得你思路有问题!(A&&(B||C))||(D&&(B||C))||(E&&(B||C))
你就没想过(A||D||E)&&(B||C)
2 楼 whz137458 2015-04-09  
我觉得你思路有问题!(A&&B||C)||(D&&B||C)||(E&&B||C)
你就没想过(A||D||E)&&(B||C)
1 楼 cf2huihui 2013-03-06  
谢谢,帮助很大

相关推荐

    lucene,lucene教程,lucene讲解

    第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。 第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。 public void add(Query query, BooleanClause.Occur occur) BooleanClause...

    lucene.NET 中文分词

    lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮 lucene.NET 中文分词 高亮

    lucene 3.0 API 中文帮助文档 chm

    lucene 3.0 API中文帮助,学习的人懂得的

    lucene实例lucene实例

    lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例

    lucene7.3常用jar包

    You should see the Lucene JAR file in the core/ directory you created when you extracted the archive -- it should be named something like lucene-core-{version}.jar. You should also see files called ...

    Lucene关于几种中文分词的总结

    Lucene关于几种中文分词的总结

    Lucene中文分词器包

    来自“猎图网 www.richmap.cn”基于IKAnalyzer分词算法的准商业化Lucene中文分词器。 1. 正向全切分算法,42万汉字字符/每秒的处理能力(IBM ThinkPad 酷睿I 1.6G 1G内存 WinXP) 2. 对数量词、地名、路名的...

    Lucene的中文分词方法设计与实现

    本文设计实现了一个中文分词模块,其主要研究目的在于寻找更为有效的中文词汇 处理方法,提高全文检索系统的中文处理能力.整个模块基于当前最流行的搜索引擎架构 Lucene,实现了带有歧义消除功能的正向最大匹配算法...

    比较全面的一个入门 lucene

    比较全面的一个入门 比较全面的一个入门 比较全面的一个入门 比较全面的一lucene个入门 比较全面的一个入门

    lucene +中文分词

    Lucene 与中文分词的结合

    Lucene中的FST算法描述

    描述了Lucene中如何使用FST算法构建term的内存索引,使用了很多图,直观的展现了FST图的构建流程,能够对想了解lucene内部实现机制原理的同学有帮助。

    lucene工作原理.docx

    lucene工作原理.docxlucene工作原理.docxlucene工作原理.docx

    lucene的一个实用例子

    lucene的一个例子,放在这里方便大家学习,本人会不断分享我的个人资源

    lucene-core-7.2.1-API文档-中文版.zip

    赠送jar包:lucene-core-7.2.1.jar; 赠送原API文档:lucene-core-7.2.1-javadoc.jar; 赠送源代码:lucene-core-7.2.1-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.2.1.pom; 包含翻译后的API文档:lucene...

    lucene3.0 lucene3.0

    lucene3.0 lucene3.0 lucene3.0 lucene3.0 lucene3.0

    Lucene中文分词器组件

    Lucene中文分词器组件,不错的。

    lucene学习lucene学习

    lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习...

    java Lucene初级教程

     Lucene是一个全文搜索框架,而不是应用产品。因此它并不像www.baidu.com 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。 2 lucene的工作方式  lucene提供的服务实际包含两部分:一...

    Lucene的一个毕业设计

    我做的一个Lucene的毕业设计,例子比较简单,但是能学到Lucene的大概的使用过程。

    Lucene在web项目中的应用

    Lucene在web项目中的应用,孔浩老师讲的,从建立索引-搜索-分词,到在留言项目中的应用,适合搜索初学者代码练习...

Global site tag (gtag.js) - Google Analytics