Lucene第二讲——索引与搜索

一、Feild域

  1.Field域的属性

    是否分词:Tokenized    

      是:对该field存储的内容进行分词,分词的目的,就是为了索引。

      否:不需要对field存储的内容进行分词,不分词,不代表不索引,而是将整个内容进行索引。

    是否索引:Indexed    

      是:将分好的词进行索引,索引的目的,就是为了搜索。

      否:不索引,也就是不对该field域进行搜索。

    是否存储:Stored

      是:将field域中的内容存储到文档域中。存储的目的,就是为了搜索页面显示取值用的。

      否:不将field域中的内容存储到文档域中。不存储,则搜索页面中没法获取该field域的值。

  2.常用Field:

  

Field类

数据类型

Analyzed

是否分词

Indexed

是否索引

Stored

是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等)

是否存储在文档中用Store.YES或Store.NO决定

LongField(FieldName, FieldValue,Store.YES)

Long型

Y

Y

Y或N

这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格)

是否存储在文档中用Store.YES或Store.NO决定

StoredField(FieldName, FieldValue)

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field

不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

字符串

Y

Y

Y或N

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

    完整类图如下:

    Lucene第二讲——索引与搜索

  按照这个改造入门程序的Field的用法:

        // 创建文档中的Field域,Store可以确定是否存储到文档域中
// ID,使用StringField;分词:否;索引:是;存储:是
Field idField = new StringField("id", book.getId().toString(), Field.Store.YES);
// name 使用TextField;分词:是;索引:是;存储:是
Field nameField = new TextField("name", book.getName(), Field.Store.YES);
// price 使用FloatField;分词:是;索引:是;存储:是
Field priceField = new FloatField("price", book.getPrice(), Field.Store.YES);
// pic 不分词不索引,但存储
Field picField = new StoredField("pic", book.getPic());
// description 分词索引不存储
Field descriptionField = new TextField("description", book.getDescription(), Field.Store.NO);

  然后删掉索引,重新生成一下索引

 二、索引的维护  

  包含索引的 增删改等维护操作

  1.增加索引:

调用 indexWriter.addDocument(doc)添加索引。

  //参考入门程序

  2.删除索引:

  根据Term删除:Term是索引库中的最小单位,也就是索引结构图索引域的 组成部分。

// 删除索引
@Test
public void deleteIndex() throws Exception {
// 1、指定索引库目录
Directory directory = FSDirectory.open(new File("E:\\11-index\\0720"));
// 2、创建IndexWriterConfig
IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
new StandardAnalyzer());
// 3、 创建IndexWriter
IndexWriter writer = new IndexWriter(directory, cfg);
// 4、通过IndexWriter来删除索引
// b)、删除指定索引
writer.deleteDocuments(new Term("filename", "apache"));
// 5、关闭IndexWriter
writer.close();
}

  //删除的是一个document对象,也就是类似数据库删除一条记录,根据id删除也就相当于SQL中delById()

  想要删除全部:

    writer.deleteAll();

  3.修改索引

  需要先查后改,需要先找到需要修改的索引,再提供新的值即可

// 修改索引
@Test
public void updateIndex() throws Exception {
// 1、指定索引库目录
Directory directory = FSDirectory.open(new File("E:\\11-index\\0720"));
// 2、创建IndexWriterConfig
IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
new StandardAnalyzer());
// 3、 创建IndexWriter
IndexWriter writer = new IndexWriter(directory, cfg);
// 4、通过IndexWriter来修改索引
// a)、创建修改后的文档对象
Document document = new Document(); // 文件名称
Field filenameField = new StringField("filename", "updateIndex", Store.YES);
document.add(filenameField); // 修改指定索引为新的索引
writer.updateDocument(new Term("filename", "apache"), document); // 5、关闭IndexWriter
writer.close();
}

  //若未查询到结果,则直接新增

三、搜索

  1.通过Query子类来创建查询对象

    Query子类常用的有:TermQuery、NumericRangeQuery、BooleanQuery

    TermQuery——精确的词项查询

Query query = new TermQuery(new Term("name", "lucene"))
package com.itheima.lucene.first;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test; /**
*  
* <p>
* Title: IndexSearch
* </p>
*  
* <p>
* Description: TODO(这里用一句话描述这个类的作用) 
* <p>
* <p>
* Company: www.itcast.com
* </p>
*  @author 传智.关云长   @date 2015-12-27 上午11:05:35    @version 1.0
*/
public class IndexSearch { private void doSearch(Query query) {
// 创建IndexSearcher
// 指定索引库的地址
try {
File indexFile = new File("E:\\11-index\\hm19\\");
Directory directory = FSDirectory.open(indexFile);
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 通过searcher来搜索索引库
// 第二个参数:指定需要显示的顶部记录的N条
TopDocs topDocs = searcher.search(query, 10); // 根据查询条件匹配出的记录总数
int count = topDocs.totalHits;
System.out.println("匹配出的记录总数:" + count);
// 根据查询条件匹配出的记录
ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) {
// 获取文档的ID
int docId = scoreDoc.doc; // 通过ID获取文档
Document doc = searcher.doc(docId);
System.out.println("商品ID:" + doc.get("id"));
System.out.println("商品名称:" + doc.get("name"));
System.out.println("商品价格:" + doc.get("price"));
System.out.println("商品图片地址:" + doc.get("pic"));
System.out.println("==========================");
// System.out.println("商品描述:" + doc.get("description"));
}
// 关闭资源
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void indexSearch() throws Exception {
// 创建query对象
// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致
// 第一个参数:默认搜索的域的名称
QueryParser parser = new QueryParser("description",
new StandardAnalyzer()); // 通过queryparser来创建query对象
// 参数:输入的lucene的查询语句(关键字一定要大写)
Query query = parser.parse("description:java AND lucene"); doSearch(query); } @Test
public void termQuery() {
// 创建TermQuery对象
Query query = new TermQuery(new Term("description", "java")); doSearch(query);
} @Test
public void numericRangeQuery() { // 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query query = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); doSearch(query);
} @Test
public void booleanQuery() {
// 创建BooleanQuery
BooleanQuery query = new BooleanQuery();
// 创建TermQuery对象
Query q1 = new TermQuery(new Term("description", "lucene"));
// 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query q2 = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); // 组合关系代表的意思如下:
// 1、MUST和MUST表示“与”的关系,即“交集”。
// 2、MUST和MUST_NOT前者包含后者不包含。
// 3、MUST_NOT和MUST_NOT没意义
// 4、SHOULD与MUST表示MUST,SHOULD失去意义;
// 5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
// 6、SHOULD与SHOULD表示“或”的概念。 query.add(q1, Occur.MUST_NOT);
query.add(q2, Occur.MUST_NOT); doSearch(query);
} @Test
public void multiFieldQueryParser() throws Exception {
// 创建7.3.2 MultiFieldQueryParser
// 默认搜索的多个域的域名
String[] fields = { "name", "description" };
Analyzer analyzer = new StandardAnalyzer();
Map<String, Float> boosts = new HashMap<String, Float>();
boosts.put("name", 200f);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,
analyzer, boosts); // Query query = parser.parse("name:lucene OR description:lucene");
Query query = parser.parse("java"); System.out.println(query); doSearch(query);
}
}

     NumericRangeQuery——数字范围查询

Query query = NumericRangeQuery.newLongRange("size", 1l, 100l, true,true);
package com.itheima.lucene.first;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test; /**
*  
* <p>
* Title: IndexSearch
* </p>
*  
* <p>
* Description: TODO(这里用一句话描述这个类的作用) 
* <p>
* <p>
* Company: www.itcast.com
* </p>
*  @author 传智.关云长   @date 2015-12-27 上午11:05:35    @version 1.0
*/
public class IndexSearch { private void doSearch(Query query) {
// 创建IndexSearcher
// 指定索引库的地址
try {
File indexFile = new File("E:\\11-index\\hm19\\");
Directory directory = FSDirectory.open(indexFile);
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 通过searcher来搜索索引库
// 第二个参数:指定需要显示的顶部记录的N条
TopDocs topDocs = searcher.search(query, 10); // 根据查询条件匹配出的记录总数
int count = topDocs.totalHits;
System.out.println("匹配出的记录总数:" + count);
// 根据查询条件匹配出的记录
ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) {
// 获取文档的ID
int docId = scoreDoc.doc; // 通过ID获取文档
Document doc = searcher.doc(docId);
System.out.println("商品ID:" + doc.get("id"));
System.out.println("商品名称:" + doc.get("name"));
System.out.println("商品价格:" + doc.get("price"));
System.out.println("商品图片地址:" + doc.get("pic"));
System.out.println("==========================");
// System.out.println("商品描述:" + doc.get("description"));
}
// 关闭资源
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void indexSearch() throws Exception {
// 创建query对象
// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致
// 第一个参数:默认搜索的域的名称
QueryParser parser = new QueryParser("description",
new StandardAnalyzer()); // 通过queryparser来创建query对象
// 参数:输入的lucene的查询语句(关键字一定要大写)
Query query = parser.parse("description:java AND lucene"); doSearch(query); } @Test
public void termQuery() {
// 创建TermQuery对象
Query query = new TermQuery(new Term("description", "java")); doSearch(query);
} @Test
public void numericRangeQuery() { // 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query query = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); doSearch(query);
} @Test
public void booleanQuery() {
// 创建BooleanQuery
BooleanQuery query = new BooleanQuery();
// 创建TermQuery对象
Query q1 = new TermQuery(new Term("description", "lucene"));
// 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query q2 = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); // 组合关系代表的意思如下:
// 1、MUST和MUST表示“与”的关系,即“交集”。
// 2、MUST和MUST_NOT前者包含后者不包含。
// 3、MUST_NOT和MUST_NOT没意义
// 4、SHOULD与MUST表示MUST,SHOULD失去意义;
// 5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
// 6、SHOULD与SHOULD表示“或”的概念。 query.add(q1, Occur.MUST_NOT);
query.add(q2, Occur.MUST_NOT); doSearch(query);
} @Test
public void multiFieldQueryParser() throws Exception {
// 创建7.3.2 MultiFieldQueryParser
// 默认搜索的多个域的域名
String[] fields = { "name", "description" };
Analyzer analyzer = new StandardAnalyzer();
Map<String, Float> boosts = new HashMap<String, Float>();
boosts.put("name", 200f);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,
analyzer, boosts); // Query query = parser.parse("name:lucene OR description:lucene");
Query query = parser.parse("java"); System.out.println(query); doSearch(query);
}
}

    BooleanQuery——布尔查询,实现组合条件查询。

BooleanQuery query = new BooleanQuery();
Query query1 = new TermQuery(new Term("id", "3"));
Query query2 = NumericRangeQuery.newFloatRange("price", 10f, 200f,
true, true); //MUST:查询条件必须满足,相当于AND
//SHOULD:查询条件可选,相当于OR
//MUST_NOT:查询条件不能满足,相当于NOT非
query.add(query1, Occur.MUST);
query.add(query2, Occur.SHOULD); System.out.println(query);
package com.itheima.lucene.first;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test; /**
*  
* <p>
* Title: IndexSearch
* </p>
*  
* <p>
* Description: TODO(这里用一句话描述这个类的作用) 
* <p>
* <p>
* Company: www.itcast.com
* </p>
*  @author 传智.关云长   @date 2015-12-27 上午11:05:35    @version 1.0
*/
public class IndexSearch { private void doSearch(Query query) {
// 创建IndexSearcher
// 指定索引库的地址
try {
File indexFile = new File("E:\\11-index\\hm19\\");
Directory directory = FSDirectory.open(indexFile);
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 通过searcher来搜索索引库
// 第二个参数:指定需要显示的顶部记录的N条
TopDocs topDocs = searcher.search(query, 10); // 根据查询条件匹配出的记录总数
int count = topDocs.totalHits;
System.out.println("匹配出的记录总数:" + count);
// 根据查询条件匹配出的记录
ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) {
// 获取文档的ID
int docId = scoreDoc.doc; // 通过ID获取文档
Document doc = searcher.doc(docId);
System.out.println("商品ID:" + doc.get("id"));
System.out.println("商品名称:" + doc.get("name"));
System.out.println("商品价格:" + doc.get("price"));
System.out.println("商品图片地址:" + doc.get("pic"));
System.out.println("==========================");
// System.out.println("商品描述:" + doc.get("description"));
}
// 关闭资源
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void indexSearch() throws Exception {
// 创建query对象
// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致
// 第一个参数:默认搜索的域的名称
QueryParser parser = new QueryParser("description",
new StandardAnalyzer()); // 通过queryparser来创建query对象
// 参数:输入的lucene的查询语句(关键字一定要大写)
Query query = parser.parse("description:java AND lucene"); doSearch(query); } @Test
public void termQuery() {
// 创建TermQuery对象
Query query = new TermQuery(new Term("description", "java")); doSearch(query);
} @Test
public void numericRangeQuery() { // 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query query = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); doSearch(query);
} @Test
public void booleanQuery() {
// 创建BooleanQuery
BooleanQuery query = new BooleanQuery();
// 创建TermQuery对象
Query q1 = new TermQuery(new Term("description", "lucene"));
// 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query q2 = NumericRangeQuery.newFloatRange("price", 55f, 60f, true,
false); // 组合关系代表的意思如下:
// 1、MUST和MUST表示“与”的关系,即“交集”。
// 2、MUST和MUST_NOT前者包含后者不包含。
// 3、MUST_NOT和MUST_NOT没意义
// 4、SHOULD与MUST表示MUST,SHOULD失去意义;
// 5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
// 6、SHOULD与SHOULD表示“或”的概念。 query.add(q1, Occur.MUST_NOT);
query.add(q2, Occur.MUST_NOT); doSearch(query);
} @Test
public void multiFieldQueryParser() throws Exception {
// 创建7.3.2 MultiFieldQueryParser
// 默认搜索的多个域的域名
String[] fields = { "name", "description" };
Analyzer analyzer = new StandardAnalyzer();
Map<String, Float> boosts = new HashMap<String, Float>();
boosts.put("name", 200f);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,
analyzer, boosts); // Query query = parser.parse("name:lucene OR description:lucene");
Query query = parser.parse("java"); System.out.println(query); doSearch(query);
}
}

  2.通过QueryParser来创建查询对象

    QueryParser(可以使用lucene语法,常用)、MultiFieldQueryParser

    QueryParser

    通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询。

    示例:

@Test
public void testQueryParser() throws Exception {
// 创建QueryParser
// 第一个参数:默认域名
// 第二个参数:分词器
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
// 指定查询语法 ,如果不指定域,就搜索默认的域
Query query = queryParser.parse("lucene");
System.out.println(query);
// 2、 执行搜索
doSearch(query); }

  

    MultiFieldQueryParser——多域查询

@Test
public void testMultiFieldQueryParser() throws Exception {
// 可以指定默认搜索的域是多个
String[] fields = { "name", "description" };
// 创建一个MulitFiledQueryParser对象
QueryParser parser = new MultiFieldQueryParser(fields, new IKAnalyzer());
// 指定查询语法 ,如果不指定域,就搜索默认的域
Query query = parser.parse("lucene");
// 2、 执行搜索
doSearch(query);
}

  3.查询语法

    1.基础查询语法  

    域名+“:”+搜索的关键字

    例如:content:java

    2.范围查询

    域名+“:”+[最小值 TO 最大值]

    例如:size:[1 TO 1000]

    //注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。

    3.条件查询

    1)+条件1 +条件2:两个条件之间是并且的关系and

      例如:+filename:apache +content:apache

    2)+条件1 条件2:必须满足第一个条件,忽略第二个条件

      例如:+filename:apache content:apache

    3)条件1 条件2:两个条件满足其一即可。

      例如:filename:apache content:apache

    4)-条件1 条件2:必须不满足条件1,要满足条件2

      例如:-filename:apache content:apache

  4.TopDocs

    Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)

    TopDocs.totalHits:是匹配索引库中所有记录的数量

    TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n

四、相关度排序

  1.什么是相关度

    相关度排序是查询结果按照与查询关键字的相关性进行排序,越相关的越靠前。比如搜索“Lucene”关键字,与该关键字最相关的文章应该排在前边。

  2.相关度打分

  Lucene对查询关键字和索引文档的相关度进行打分,得分高的就排在前边。如何打分呢?Lucene是在用户进行检索时实时根据搜索的关键字计算出来的,分两步:

  1)计算出词(Term)的权重

  2)根据词的权重值,计算文档相关度得分

  什么是词的权重?

  通过索引部分的学习,明确索引的最小单位是一个Term(索引词典中的一个词),搜索也是要从Term中搜索,再根据Term找到文档,Term对文档的重要性称为权重,影响Term权重有两个因素:

  Tf

  词在同一个文档中出现的频率

  Tf越高,说明词的权重越高

Df

  词在多个文档中出现的频率

  Df越高,说明词的权重越低

  以上是自然打分的规则。

  3.设置boost值影响打分

  Boost:加权值,默认是1.0f。

  设置加权值可以在创建索引时设置,也可以在查询时设置。

  Boost值是设置到Field域上的

    1.创建时指定(常用)

@Test
public void setBoost4createIndex() throws Exception {
// 创建分词器
Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
analyzer);
Directory directory = FSDirectory.open(new File("E:\\11-index\\0728"));
// 创建IndexWriter对象,通过它把分好的词写到索引库中
IndexWriter writer = new IndexWriter(directory, cfg); Document doc = new Document();
Field id = new StringField("id", "11", Store.YES);
Field description = new TextField("description", "测试设置BOOST值 lucene",
Store.YES);
// 设置boost
description.setBoost(10.0f);
// 把域添加到文档中
doc.add(id);
doc.add(description);
writer.addDocument(doc);
// 关闭IndexWriter
writer.close();
}

    2..在MultiFieldQueryParser创建时设置boost值。

  Lucene第二讲——索引与搜索

 五、中文分词器

  1.什么是中文分词器

  学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开。而中文则以字为单位,字又组成词,字和词再组成句子。所以对于英文,我们可以简单以空格判断某个字符串是否为一个单词

  比如I love China,love 和 China很容易被程序区分开来;但中文“我爱中国”就不一样了,电脑不知道“中国”是一个词语还是“爱中”是一个词语。把中文的句子切分成有意义的词,就是中文分词,也称切词。我爱中国,分词的结果是:我 爱 中国。

  2.Lucene自带分词器

   StandardAnalyzer

  单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
       效果:“我”、“爱”、“中”、“国”。

  CJKAnalyzer

  二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。

  3.第三方中文分词器

  这里暂时只介绍实际使用的: IKAnalyzer

  其它例如 smartcn等暂时不展开。

  如何使用:

    相关的使用步骤可以参见:http://blog.csdn.net/cyxlzzs/article/details/7999212

    1.添加jar

    2.修改分词器:

// 创建中文分词器
Analyzer analyzer = new IKAnalyzer();

    3.从ikanalyzer包中拷贝配置文件到classpath下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties> <comment>IK Analyzer 扩展配置</comment>
<!-- 用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">dicdata/mydict.dic</entry>
<!-- 用户可以在这里配置自己的扩展停用词字典 -->
<entry key="ext_stopwords">dicdata/ext_stopword.dic</entry> </properties> 

  如果想配置扩展词和停用词,就创建扩展词的文件和停用词的文件,文件的编码要是utf-8。

  注意:不要用记事本保存扩展词文件和停用词文件那样的话格式中是含有bom的。(使用IDE或者Editplus)

  添加扩展词文件:ext.dic,内容如下:

  Lucene第二讲——索引与搜索

上一篇:51nod1158 全是1的最大子矩阵


下一篇:ISP PIPLINE (九_2) Denoise 之 time domain denoise