Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

释放双眼,带上耳机,听听看~!

原文:Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

2.1.2 可以使用的内置分词

**** 

简单的分词方式并不能满足需求。前文说过Lucene.Net内置分词中StandardAnalyzer分词还算比较实用(见1.1.2小节)。StandardAnalyzer为什么能满足我们的部分需求,而它又有哪些不足呢?看分词的好坏还是要从效果说起。简单的说,在中英文混合的情况下,StandardAnalyzer会把英文按空格拆,而中文则按单字拆。因为中文是按单字拆,所以对分词的准确性起到了干扰,搜索结果就会不准确,至少理论上是这样的。但是实际上StandardAnalyzer分词器并没有我们想的那么差劲。因为搜索不光与分词有关,还和查询的逻辑有关,这个会在第四章讲搜索的时候讲。作为其中的一个重要要素的,可以说是基础的分词器,当然还是扮演了很关键的角色,查询的逻辑是以分词为基础的。分词是原石,而查询逻辑则能对它雕琢。

 

事实上如果没有用过StandardAnalyzer分词器,没有用它来解决一些问题,并且找到有哪些地方不足,那并不能弄清楚你要什么样的分词器。比如,现在有一些内容,用StandardAnalyzer作为分词器已经建立好了索引,接下来,进行查询操作。

 

 

代码 2.1.2.1

 

Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
Code

 1Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 System;

 2
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.Analysis;

 3
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.Analysis.Standard;

 4
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.Documents;

 5
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.Index;

 6
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.QueryParsers;

 7
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 Lucene.Net.Search;

 8
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 NUnit.Framework;

 9
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
using
 System.Collections.Generic;

10
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

11
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
namespace
 Test

12
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

13
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)    [TestFixture]

14
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)    
public
 
class
 StandardAnalyzerCaseTest

15
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)    
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

16
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
/**/
///
 

<summary>

17
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 执行测试的入口

18
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 

</summary>

19Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
        [Test]

20
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
public
 
void
 SearcherTest()

21
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

22
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Index();

23
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            List
<
string

 list 

 
new
 List
<
string

() 
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

"
中华
"

"
中国
"

"
人民
"

"
中国人民
"

"
人民
"
 }
;

24
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            
for
 (
int
 i 

 
0
; i 
<
 list.Count; i
++
)

25
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

26
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)                Console.WriteLine(
"
搜索词:
"
 
+
 list[i]);

27
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)                Console.WriteLine(
"
结果:
"
);

28
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)                Searcher(list[i]);

29
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)                Console.WriteLine(
"

"
);

30
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            }

31
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        }

32
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

33
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
/**/
///
 

<summary>

34
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 搜索

35
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 

</summary>

36
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 
<param name="querystring">
搜索输入

</param>

37Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
        
private
 
void
 Searcher(
string
 querystring)

38
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

39
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Analyzer analyzer 

 
new
 StandardAnalyzer();

40
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            IndexSearcher searcher 

 
new
 IndexSearcher(
"
IndexDirectory
"
);

41
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            QueryParser parser 

 
new
 QueryParser(
"
content
"
, analyzer);

42
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Query query 

 parser.Parse(querystring);

43
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Hits hits 

 searcher.Search(query);

44
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            
for
 (
int
 i 

 
0
; i 
<
 hits.Length(); i
++
)

45
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

46
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)                Console.WriteLine(hits.Doc(i).Get(
"
content
"
));

47
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            }

48
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        }

49
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

50
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
/**/
///
 

<summary>

51
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 索引数据

52
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 

</summary>

53Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
        
private
 
void
 Index()

54
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

55
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Analyzer analyzer 

 
new
 StandardAnalyzer();

56
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            IndexWriter writer 

 
new
 IndexWriter(
"
IndexDirectory
"
, analyzer, 
true
);

57
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            AddDocument(writer, 
"
中华人民共和国
"
);

58
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            AddDocument(writer, 
"
中国人民解放军
"
);

59
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            AddDocument(writer, 
"
人民是伟大的,祖国是伟大的。
"
);

60
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            AddDocument(writer, 
"
你站在边上,我站在中央。
"
);

61
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            writer.Optimize();

62
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            writer.Close();

63
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        }

64
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
/**/
///
 

<summary>

65
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 为索引准备数据

66
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 

</summary>

67
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 
<param name="writer">
索引实例

</param>

68
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
///
 
<param name="content">
需要索引的数据

</param>

69Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
        
void
 AddDocument(IndexWriter writer, 
string
 content)

70
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)
{

71
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            Document document 

 
new
 Document();

72
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            document.Add(
new
 Field(
"
content
"
, content, Field.Store.YES, Field.Index.TOKENIZED));

73
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)            writer.AddDocument(document);

74
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)        }

75
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)    }

76
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)}

77
Lucene.Net 2.3.1开发介绍 —— 二、分词(四)

 

代码2.1.2.1,先是把四句话进行了索引,尔后,分别用5个词进行了查询。运行结果:

 

搜索词:中华
结果:
中华人民共和国

搜索词:中国
结果:
中国人民解放军

搜索词:人民
结果:
中华人民共和国
中国人民解放军
人民是伟大的,祖国是伟大的。

搜索词:中国人民
结果:
中国人民解放军

搜索词:人民
结果:
中华人民共和国
中国人民解放军
人民是伟大的,祖国是伟大的。

发现结果还很不错,结果都在我们的预料之中,StandardAnalyzer分词器很好啊!为什么说它不行呢?接着,用StandardAnalyzer分词器为网站建立了索引,然后开始使用,问题就出现了。用户输入的往往不是一个词,而是几个词,或者干脆就是一句话。把问题简化一下,就用代码2.1.2.1作为模型。假如,现在索引进了四句话变成这样:

(1)、英语单词,语法,口语都很重要。

(2)、口语,语法,单词都是英语的重要组成部分。

(3)、我们要学好英语不但要学语法,单词还有口语。

(4)、对于学英语,只掌握单词语法,还是没办法跟别人沟通,必须能说出流利的口语。

 

假设,我们要搜索这四句话,也用5中输入:
(1)、英语

(2)、语法

(3)、单词

(4)、口语

(5)、英语单词

 

测试,结果对于输入的1,2,3,4前四个关键词,没问题,而第5个只能搜索到一个结果,这就纳闷了,明明每句话都包含了“英语”,“单词”这两个词汇,为什么不行呢?而把输入词换成“英语口语”,更邪门!没了,一个结果都没有。这是为什么呢?这个要从Lucene.Net的查询表达式说起。

 

话说,为了让Lucene.Net能灵活得搜索,因此,Lucene.Net引入了查询表达式,就和T-Sql的查询语句差不多,只是表现的代码不一样。现在对代码2.1.2.1做一个调整,在Query query = parser.Parse(querystring);语句下面加一句“Console.WriteLine(query.ToString());”,这个输出的就是查询表达式。而对于“英语单词”这个词,代码2.1.2.1会把它解析为——content:"英 语 单 词"——意思是在content字段,找“英”,“语”,“单”,“词”这四个字,并且,这四个字要连在一起。这显然不是我们想要的。而在用baidu或者google搜索的时候,如果输入的多个词之间加上空格就不一样了,同样,放到这里来试试。把词变成“英语 单词”,测试一下。

测试结果:

 

搜索词:英语 单词
结果:
content:"英 语" content:"单 词"
英语单词,语法,口语都很重要。
口语,语法,单词都是英语的重要组成部分。
我们要学好英语不但要学语法,单词还有口语。
对于学英语,只掌握单词语法,还是没办法跟别人沟通,必须能说出流利的口语。

 

可以搜素到了,而表达式也变成了——content:"英 语" content:"单 词"。

现在将面临新的问题:怎么才能把“英语单词”变成“英语 单词”。你不能期望用户总会输入搜索关键词后,逐个加上空格区分。而事实上一个新问题又产生了。修正一个错误会产生另外两个错误,前人说的太正确了。在这个例子里可能看不出来,把例子换一下,把上面第四句话换成“好好学英语”。

 

测试结果:


搜索词:英语 单词
结果:
content:"英 语" content:"单 词"
英语单词,语法,口语都很重要。
口语,语法,单词都是英语的重要组成部分。
我们要学好英语不但要学语法,单词还有口语。
好好学英语。

 

“好好学英语”没有包含“单词”这个词,但是却被搜索到了。这是为什么?玩我了吧?嘿嘿,那是因为——content:"英 语" content:"单 词"——这个表达式是或者的关系,要是变成并且的关系,是不是能解决问题呢?尝试手动改造下表达式。把表达式变成“+content:"英 语" +content:"单 词"”,测试:

 


搜索词:+content:"英 语" +content:"单 词"
结果:
+content:"英 语" +content:"单 词"
英语单词,语法,口语都很重要。
口语,语法,单词都是英语的重要组成部分。
我们要学好英语不但要学语法,单词还有口语。

 

very good !这个才是我们想要的嘛!怎么自己构造表达式,这个还是留到第四章来系统的讲。既然“+content:"英 语" +content:"单 词"”,可以用,那是不是“+content:"英" +content:"语" +content:"单" +content:"词"”,也可以使用呢?嘿嘿自己试试看吧。

 

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索