全文搜索之lucence入门(三) 查询索引

我们可以使用luke工具来查询我们本地的索引存储信息。

查询的流程如下

在lucene中query有几种基本是查询类型。

词项查询  TermQuery  
短语查询  PhraseQuery
布尔查询  BooleanQuery
正则查询  RegexpQuery
模糊查询  FuzzyQuery
前缀查询  PrefixQuery
通配符查询  WildcardQuery

范围查询  TermRangeQuery

这里的查询都是以词项为单位,每个查询的操作对象都是一个或多个词项。这里有一点需要注意的是短语查询查询对应的Field必须存储了位置信息, 不然在执行查询解析的时候会报错,提示没有该字段的位置信息。除了上面这些基本查询还有其他的类型。还有一种高级的查询类型就是QueryParse,它通过定义了一些规则就跟sql语法的规则似的,我们可以根据它的语法来使用查询,而不是自己去组装基础查询。

QueryParse需要我们指定一个默认的查询字段。当我们没有对值指定字段的时候就会使用默认字段。

语法结构=  字段名:值。存在对多个字段操作时使用空格隔开。在值这个位置我们可以使用上面的基本查询类型。比如name:*电脑,这个等于一个通配符查询,price:[200 TO 500}这个等于范围查询,[表示不包含边界,{包含边界,name:电脑~2,这个等于模糊查询中我们是指的模糊值为2,在模糊查询中,模糊值最大只能是2,它只有3个值可以选择,0,1,2. name:"台式电脑"~2,这个等于临近查询,会先对引号里面字符串分词,~表示分词后词项之间的跨度。name:电脑 price:[200 TO *] 这个等于一个词项查询和一个范围查询组成的布尔查询。注意中间是有空格的,这个表示或的操作。name:电脑 +price:[200 TO *]这个表示name包含电脑且价格在200以上的,是一个AND操作,我们也可以用AND ,这里是区分大小写的。name:电脑 +price:[200 TO *]=name:电脑 AND price:[200 TO *];name:电脑 NOT price:[200 TO *} 这个等于name包含电脑 切价格不在200以上的。

布尔操作符解释

AND = + ;AND是双目运算,+是单目,表示这个条件必须满足

OR = 不写   ;OR 跟sql中的OR是一个意思

NOT = -  ;- 单目运算,也是必须满足的条件

还有一个^,我们在词项或短语中使用这个符号表示对其得分进行加权计算

简单查询使用代码

Analyzer analyzer = new IKAnalyzer(true);
		QueryParser qp = new QueryParser("name", analyzer);
		Query query = qp.parse("苹笔记本电脑~1");
//		Query query = qp.parse("笔*脑");
//		+单目运算  等同于 AND, !等同于- 表示否,相当于sql中的 and field!=。
//		Query query = qp.parse("type:电脑  price:[2000 TO 9000}");
//		Query query = qp.parse("type:游戏机 笔记本电脑  -price:[1000 TO 4000}");
//		Query query = qp.parse("type:电脑  华为^3 +price:{2000 TO 9000}");
		
		//范围查询,
//		Query query = new TermRangeQuery("price", new BytesRef("2000"), new BytesRef("9000"), true, false);
		
		//词项查询
//		Query query = new TermQuery(new Term("name", "苹果"));
		//模糊查询
//		Query query = new FuzzyQuery(new Term("type", "电脑"), 2);
		//短语查询
//		Query query = new PhraseQuery(2,"type", "电脑","手机");   type字段我们没有存储字段信息,执行会报错
//		Query query = new PhraseQuery(2,"name", "台式","电脑");
		//前缀查询
//		Query query = new PrefixQuery(new Term("name","笔"));
		//通配符查询
//		Query query = new WildcardQuery(new Term("name","???电脑"));
//		Query query = new WildcardQuery(new Term("name","*电脑"));
		//正则查询
//		Query query = new RegexpQuery(new Term("name","台式|笔记本电脑"));
		//不二查询
//		Query query1 = new TermQuery(new Term("name", "台式"));
//		Query query2 = new TermQuery(new Term("name", "电脑"));
//		BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
//		booleanQueryBuilder.add(query1, Occur.SHOULD);
//		booleanQueryBuilder.add(query2, Occur.MUST);
//		BooleanQuery query = booleanQueryBuilder.build();
		
		System.out.println(query.toString());
		FSDirectory directory = FSDirectory.open((new File("d:/test/index2").toPath()));
		DirectoryReader reader = DirectoryReader.open(directory);
		IndexSearcher searcher = new IndexSearcher(reader);
//		TopDocs docs = searcher.search(query, 10);
		TopDocs docs = searcher.search(query, 10,new Sort(new SortField("price", Type.DOUBLE)));   //按price排序
		System.out.println(docs.scoreDocs.length);
		for(ScoreDoc scoreDoc :docs.scoreDocs){
			Document doc = searcher.doc(scoreDoc.doc);
			System.out.println(scoreDoc.score);
			System.out.println(doc.getBinaryValue("name").utf8ToString());
		}
		
		reader.close();
		directory.close();

lucene搜索分页过程中,可以有两种方式 一种是将搜索结果集直接放到session中,但是假如结果集非常大,同时又存在大并发访问的时候,很可能造成服务器的内存不足,而使服务器宕机 还有一种是每次都重新进行搜索,这样虽然避免了内存溢出的可能,但是,每次搜索都要进行一次IO操作,如果大并发访问的时候,你要保证你的硬盘的转速足够的快,还要保证你的cpu有足够高的频率 而我们可以将这两种方式结合下,每次查询都多缓存一部分的结果集,翻页的时候看看所查询的内容是不是在已经存在在缓存当中,如果已经存在了就直接拿出来,如果不存在,就进行查询后,从缓存中读出来. 比如:现在我们有一个搜索结果集 一个有100条数据,每页显示10条,就有10页数据. 安装第一种的思路就是,我直接把这100条数据缓存起来,每次翻页时从缓存种读取 而第二种思路就是,我直接从搜索到的结果集种显示前十条给第一页显示,第二页的时候,我在查询一次,给出10-20条数据给第二页显示,我每次翻页都要重新查询种思路就变成了 我第一页仅需要10条数据,但是我一次读出来50条数据,把这50条数据放入到缓存当中,当我需要10--20之间的数据的时候,我的发现我的这些数据已经在我的缓存种存在了,我就直接存缓存中把数据读出来,少了一次查询,速度自然也提高了很多. 如果我访问第六页的数据,我就把我的缓存更新一次.这样连续翻页10次才进行两次IO操作 同时又保证了内存不容易被溢出.而具体缓存设置多少,要看你的服务器的能力和访问的人数来决定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值