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

2.1.2 可以使用的内置分词

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

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

代码 2.1.2.1
 
Code 1using System; 2using Lucene.Net.Analysis; 3using Lucene.Net.Analysis.Standard; 4using Lucene.Net.Documents; 5using Lucene.Net.Index; 6using Lucene.Net.QueryParsers; 7using Lucene.Net.Search; 8using NUnit.Framework; 9using System.Collections.Generic;1011namespace Test12{13    [TestFixture]14    public class StandardAnalyzerCaseTest15    {16        /**//// <summary>17        /// 执行测试的入口18        /// </summary>19        [Test]20        public void SearcherTest()21        {22            Index();23            List<string> list = new List<string>() { "中华", "中国", "人民", "中国人民", "人民" };24            for (int i = 0; i < list.Count; i++)25            {26                Console.WriteLine("搜索词:" + list[i]);27                Console.WriteLine("结果:");28                Searcher(list[i]);29                Console.WriteLine("-----------------------------------");30            }31        }3233        /**//// <summary>34        /// 搜索35        /// </summary>36        /// <param name="querystring">搜索输入</param>37        private void Searcher(string querystring)38        {39            Analyzer analyzer = new StandardAnalyzer();40            IndexSearcher searcher = new IndexSearcher("IndexDirectory");41            QueryParser parser = new QueryParser("content", analyzer);42            Query query = parser.Parse(querystring);43            Hits hits = searcher.Search(query);44            for (int i = 0; i < hits.Length(); i++)45            {46                Console.WriteLine(hits.Doc(i).Get("content"));47            }48        }4950        /**//// <summary>51        /// 索引数据52        /// </summary>53        private void Index()54        {55            Analyzer analyzer = new StandardAnalyzer();56            IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true);57            AddDocument(writer, "中华人民共和国");58            AddDocument(writer, "中国人民解放军");59            AddDocument(writer, "人民是伟大的,祖国是伟大的。");60            AddDocument(writer, "你站在边上,我站在中央。");61            writer.Optimize();62            writer.Close();63        }64        /**//// <summary>65        /// 为索引准备数据66        /// </summary>67        /// <param name="writer">索引实例</param>68        /// <param name="content">需要索引的数据</param>69        void AddDocument(IndexWriter writer, string content)70        {71            Document document = new Document();72            document.Add(new Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));73            writer.AddDocument(document);74        }75    }76}77

代码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:\"词\"”,也可以使用呢?嘿嘿自己试试看吧。

Lucene.Net 2.3.1开发介绍 —— 二、分词(四)的更多相关文章

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

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(六) Lucene.Net的上一个版本是2.1,而在2.3.1版本中才引入了Next(Token)方法重载,而ReusableStrin ...

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

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(五) 2.1.3 二元分词 上一节通过变换查询表达式满足了需求,但是在实际应用中,如果那样查询,会出现另外一个问题,因为,那样搜索,是只 ...

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

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(三) 1.3 分词器结构 1.3.1 分词器整体结构 从1.2节的分析,终于做到了管中窥豹,现在在Lucene.Net项目中添加一个类关 ...

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

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(二) 1.2.分词的过程 1.2.1.分词器工作的过程 内置的分词器效果都不好,那怎么办?只能自己写了!在写之前当然是要先看看内置的分词 ...

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

    原文:Lucene.Net 2.3.1开发介绍 -- 二.分词(一) Lucene.Net中,分词是核心库之一,当然,也可以将它独立出来.目前Lucene.Net的分词库很不完善,实际应用价值不高.唯 ...

  6. Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)

    原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(二) 4.3 表达式用户搜索,只会输入一个或几个词,也可能是一句话.输入的语句是如何变成搜索条件的上一篇已经略有提及. 4.3.1 观察 ...

  7. Lucene.Net 2.3.1开发介绍 —— 三、索引(二)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(二) 2.索引中用到的核心类 在Lucene.Net索引开发中,用到的类不多,这些类是索引过程的核心类.其中Analyzer是索引建立的 ...

  8. Lucene.Net 2.3.1开发介绍 —— 三、索引(四)

    原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(四) 4.索引对搜索排序的影响 搜索的时候,同一个搜索关键字和同一份索引,决定了一个结果,不但决定了结果的集合,也确定了结果的顺序.那个 ...

  9. Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)

    原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...

随机推荐

  1. Java For循环效率试验

    非常奇怪的结果! ..! 测试方法如以下 public class Main { public static void main(String[] args){ long ti = System.cu ...

  2. Android 蓝牙( Bluetooth)耳机连接分析及实现

    Android 实现了对Headset 和Handsfree 两种profile 的支持.其实现核心是BluetoothHeadsetService,在PhoneApp 创建的时候会启动它. if ( ...

  3. weblogic中设置数据源的注意点

    一.基本概念 进入weblogic的管理页面,点击服务——>数据源,可以进行数据源的配置.通过新建,输入地址,用户名,密码等信息可以新建一个数据源. 二.发现问题 建立好数据源之后,跑项目,发现 ...

  4. JVM调优总结(十)-调优方法

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...

  5. Linux下搭建Hadoop集群

    本文地址: 1.前言 本文描述的是如何使用3台Hadoop节点搭建一个集群.本文中,使用的是三个Ubuntu虚拟机,并没有使用三台物理机.在使用物理机搭建Hadoop集群的时候,也可以参考本文.首先这 ...

  6. android 由于界面控件过多耗时处理办法

    在开发当中,有时候可能界面嵌套较多,那么导致控件实例化增多,有时候会大大影响界面加载的速度,特别在viewpage中的时候,要是第一页里面要inflate一个控件比较多的页面的时候,就会影响整个Act ...

  7. Join的实现步骤 以及连接的概念

    Join的实现步骤  以及连接的概念 我们常说连接有三种,即 交叉连接.内连接.外连接,这三者的概念很容易模糊,现在我们先放下概念,搞清楚完整连接实现的步骤: 一个完整的连接有三个步骤:.做笛卡儿积: ...

  8. SmartGit 试用过期

    smartgit是见过的最好用的git客户端, 要解决其试用版过期的问题,如下: 1.定位到文件夹 Windows: %APPDATA%\syntevo\SmartGit\OS X: ~/Librar ...

  9. C++能在三个地方创造对象,而Delphi只有一个地方

    C++能在堆栈.堆.资料区创造对象. 但是Delphi只能在堆上创造对象

  10. [置顶] Objective-C ,ios,iphone开发基础:UIAlertView使用详解

    UIAlertView使用详解 Ios中为我们提供了一个用来弹出提示框的类 UIAlertView,他类似于javascript中的alert 和c#中的MessageBox(); UIAlertVi ...