关于 Lucene 搜索语法与分词的浅显研究

分词器在创建索引与搜索之时都会用到。上文我用icu分词器实现了简单的中文分词器,却发现不能直接在搜索之时使用,会打断一些lucene搜索语法的分析。

语法汇总:https://www.likecs.com/show-95873.html

问题 / issues

比如,使用双引号进行全文搜索,"天文",普通分析器分词为:content:"天 文",我制作的自定义分词器却出现了冗余内容,结果为:content:"天文 天 文",反而查找不到任何有效内容。

有个疑问,content:"天 文"content:"天文"是否有区别?结果应该是一样的,可能效率上有区分。

问号无法在双引号内使用。其实双引号之内,空格以及标点符号是被过滤掉的,搜索之时,匹配连续的关键词。

问号,如用 muscle? 搜索 muscles。如果分词器没有特定分词,那么也是搜索不到的,比如格林尼治天文台,如果以格林?治天文台为搜索语句,那么不管是标准分词器,还是自定义分词器,都是没有任何结果,反而不如搜格林 治天文台。那是因为,标准分词器只生成单字索引,而自定义分词器也只能分词为:格林+天文台,索引里并没有存储完整的关键词。

星号同理。而且其实,使用星号问号之时,搜索语句并没有经过自定义分词器的分析,而是直接作为一个特殊的term。

修复 / workaround fix

目前,通过类似于“反射”、“反序列化”的简单方式修复自定义分词器对于双引号的打断。

因为以下经验公式应该是成立的 ——

new QueryParser(Version.LUCENE_47, "content", analyzer).parse(query.toString()) == query

所以,在第一遍 QueryParser.parse 后,得到 query.toString(),对此字符串进行魔改式修正 —— 搜索正则表达式 content:"(.?)" 以过滤掉双引号中的双字及以上词语即可,最后再次 QueryParser.parse 最终得到 query 之对象,搜索之锁钥。

附无限词典 v7.2 更新日志

我对于开源的态度是无限开放。希望能有人参与这无限开源。

v7.2

  • 修复搜索引擎无法用双引号进行全文搜索的BUG。
  • 实现搜索引擎输入栏的双引号按钮,有无选中内容均可点击。
  • 修复相机取词(目前只有实时相机取词)

代码片段:

query = new QueryParser(Version.LUCENE_47, "content", analyzer).parse(phrase);
			CMN.debug("breaked query::", query);
			boolean debug_query = true;
			if (phrase.contains("\"") || debug_query) {
				try {
					String raw = query.toString();
					Pattern p = Pattern.compile("content:\"(.+?)\"");
					Matcher m = p.matcher(raw);
					StringBuffer sb = new StringBuffer();
					boolean found = false;
					while(m.find()) {
						found = true;
						m.appendReplacement(sb, "");
						String raw_term = m.group(1);
						int now = 0, last=-1;
						// loop in "raw_term"
						while (now < raw_term.length()) {
							if (raw_term.charAt(now)==' ') {
								boolean shouldStrip = true;
								if (now-last-1 <= 1) shouldStrip = false;
								if (shouldStrip) {
									boolean quanYingWen = true;
									for (int i = last+1; i < now; i++) {
										if (WordBreakFilter.isBigram(raw_term.charAt(i))) {
											quanYingWen = false;
											break;
										}
									}
									if(quanYingWen) shouldStrip = false;
								}
								if (shouldStrip) last = now;
								else break;
							}
							now ++ ;
						}
						if (last > 0) raw_term = raw_term.substring(last+1);
						sb.append("content:\"").append(raw_term).append("\"");
					}
					if (found || debug_query)
					{
						m.appendTail(sb);
						raw = sb.toString();
						//CMN.debug("修正前 query::", query);
						query = new QueryParser(Version.LUCENE_47, "content", new StandardAnalyzer(Version.LUCENE_47)).parse(raw);
						CMN.debug("修正后 query::", query);
					}
				} catch (Exception e) {
					CMN.debug(e);
				}
			}

log :

修正前 query:: content:"格林 天文台 格 林 尼 治 天 文 台" 
修正后 query:: content:"格 林 尼 治 天 文 台" 

你可能感兴趣的:(Lucene,lucene,全文检索)