Lucene全文索引的分词Analyzer(词法分析器)带你上分

   分词Analyzer(词法分析器)

分词器是Lucene中非常重要的一个知识点,如果你面试时说你用过Lucene面试官一定会问你用的什么分词器。

    分词,也称词法分析器(或者叫语言分析器),就是指索引中的内容按什么样的方式来建立,这在全文检索中非常关键,是按英文单词建立索引,还是按中文词意建立索引;这些需要由Analyzer来指定。

对于中文,需要采用字典分词,也叫词库分词;把中文件的词全部放置到一个词库中,按某种算法来维护词库内容;如果匹配到就切分出来成为词语。通常词库分词被认为是最理想的中文分词算法。如:“我们是中国人”,效果为:“我们”、“中国人”。(可以使用SmartChineseAnalyzer,“极易分词” MMAnalyzer ,或者是“庖丁分词”分词器、IKAnalyzer。推荐使用IKAnalyzer )

    在这里我们推荐IKAnalyzer。使用时需导入IKAnalyzer.jar,并且拷贝IKAnalyzer.cfg.xml,ext_stopword.dic文件,分词器测试代码如下:

//创建索引的数据 现在写死,以后根据实际应用场景
	private String en = "oh my lady gaga"; // oh my god
	private String cn = "三大不及掩耳盗铃儿响叮当仁不让";
	private String str = "FullText Search Lucene框架的学习tmd吃鸡";
	
	
	/**
	 * 把特定字符串按特定的分词器来分词
	 * @param analyzer
	 * @param str
	 * @throws Exception
	 */
	public void testAnalyzer(Analyzer analyzer,String str) throws Exception {
		TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(str));
		// 在读取词元流后,需要先重置/重加载一次
		tokenStream.reset();
		while(tokenStream.incrementToken()){
			System.out.println(tokenStream);
		}
	}
	
	//标准分词:不支持中文
	@Test
	public void testStandardAnalyzer() throws Exception {
		
		testAnalyzer(new StandardAnalyzer(), cn);
	}
	
	//简单分词:不支持中文
	@Test
	public void testSimpleAnalyzer() throws Exception {
		testAnalyzer(new SimpleAnalyzer(), cn);
	}
	
	//二分分词:两个字是一个词
	@Test
	public void testCJKAnalyzer() throws Exception {
		testAnalyzer(new CJKAnalyzer(), cn);
	}
	
	//词典分词:从词典中查找
	@Test
	public void testSmartChineseAnalyzer() throws Exception {
		testAnalyzer(new SmartChineseAnalyzer(), cn);
	}
	
	//IK分词:从词典中查找
	// 简单使用:拷贝两个配置文件,IKAnalyzer.cfg.xml,stopword.dic拷贝一个jar包 
   // IKAnalyzer2012_V5.jar
	//       扩展词,停止词
	//  注意:打开方式,不要使用其他的,
//直接使用eclipse的text Editor, 
   //修改以后要刷新一下让项目重新编译(有时候需要有时候不需要刷新)
	
	@Test
	public void testIKAnalyzer() throws Exception {
		//true 粗密度分词(智能分词)  false 细密度分词
		testAnalyzer(new IKAnalyzer(false), str); 
	}

 

索引的添删改

    经过之前的分析,我们知道对索引的操作统一使用IndexWriter。测试代码如下:

// 数据源
	private String doc1 = "hello world";
	private String doc2 = "hello java world";
	private String doc3 = "hello lucene world";

	// 索引库目录
	private String indexPath = "F:\\ecworkspace\\lucene\\indexCRUD";
	@Test
	public void createIndex() throws IOException, ParseException {
		/**
		 * 准备工作
		 */
		// 索引目录
		Directory d = FSDirectory.open(Paths.get(indexPath));
		// 词法分析器
		Analyzer analyzer = new StandardAnalyzer();
		// 写操作核心配置对象
		IndexWriterConfig conf = new IndexWriterConfig(analyzer);
		conf.setOpenMode(OpenMode.CREATE);
		// 写操作核心对象
		IndexWriter indexWriter = new IndexWriter(d, conf);
		System.out.println(indexWriter);

		/**
		 * 操作
		 */
		Document document1 = new Document();
		document1.add(new TextField("id", "1", Store.YES));
		document1.add(new TextField("name", "doc1", Store.YES));
		document1.add(new TextField("content", doc1, Store.YES));
		indexWriter.addDocument(document1);

		Document document2 = new Document();
		document2.add(new TextField("id", "2", Store.YES));
		document2.add(new TextField("name", "doc2", Store.YES));
		document2.add(new TextField("content", doc2, Store.YES));
		indexWriter.addDocument(document2);
		Document document3 = new Document();
		document3.add(new TextField("id", "3", Store.YES));
		document3.add(new TextField("name", "doc3", Store.YES));
		document3.add(new TextField("content", doc3, Store.YES));
		indexWriter.addDocument(document3);
		/**
		 * 收尾
		 */
		indexWriter.commit();
		indexWriter.close();
		
		searchIndex();
	}

	@Test
	public void del() throws IOException, ParseException{
		/**
		 * 准备工作
		 */
		// 索引目录
		Directory d = FSDirectory.open(Paths.get(indexPath));
		// 词法分析器
		Analyzer analyzer = new StandardAnalyzer();
		// 写操作核心配置对象
		IndexWriterConfig conf = new IndexWriterConfig(analyzer);
		// 写操作核心对象
		IndexWriter indexWriter = new IndexWriter(d, conf);
		System.out.println(indexWriter);
		
		
		//删除所有
		//indexWriter.deleteAll();
		//第一种
//		QueryParser qpParser = new QueryParser("id", analyzer);
//		Query query = qpParser.parse("1");
//		indexWriter.deleteDocuments(query);
		
		//第二种
		indexWriter.deleteDocuments(new Term("id", "1"));
		
		indexWriter.commit();
		indexWriter.close();
		
		searchIndex();
	}
	
	@Test
	public void update() throws IOException, ParseException{
		/**
		 * 准备工作
		 */
		// 索引目录
		Directory d = FSDirectory.open(Paths.get(indexPath));
		// 词法分析器
		Analyzer analyzer = new StandardAnalyzer();
		// 写操作核心配置对象
		IndexWriterConfig conf = new IndexWriterConfig(analyzer);
		// 写操作核心对象
		IndexWriter indexWriter = new IndexWriter(d, conf);
		System.out.println(indexWriter);
		
		
		Document doc = new Document();
		doc.add(new TextField("id", "2", Store.YES));
		doc.add(new TextField("name", "doc2", Store.YES));
		doc.add(new TextField("content", "修改后 -的doc2", Store.YES));
		
		indexWriter.updateDocument(new Term("id","2"), doc );
		/*等价于
		 indexWriter.deleteDocuments(new Term("id", "2"));
		 indexWriter.addDocument(doc);
		 */
		indexWriter.commit();
		indexWriter.close();
		
		searchIndex();
	}
	
	
	@Test
	public void searchIndex() throws IOException, ParseException {
		// 索引目录
		Directory d = FSDirectory.open(Paths.get(indexPath));
		// 词法分析器
		Analyzer analyzer = new StandardAnalyzer();
		// 创建索引的读写对象
		IndexReader r = DirectoryReader.open(d);
		// 创建核心对象
		IndexSearcher indexSearcher = new IndexSearcher(r);

		// 查询解析器
		// 参数1:默认查询的字段
		// 参数2:分词器
		QueryParser queryParser = new QueryParser("content", analyzer);
		String queryString = "*:*";

		Query query = queryParser.parse(queryString);
		// 调用核心对象的search方法
		// 参数query: 查询对象
		// 参数 n : 前n条
		TopDocs topDocs = indexSearcher.search(query, 50);
		System.out.println("一共查询到的数量:" + topDocs.totalHits);

		// 获得数据集合
		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		for (ScoreDoc scoreDoc : scoreDocs) {
			// 获取文档ID
			int docId = scoreDoc.doc;
			// 通过docId获取Document
			Document doc = indexSearcher.doc(docId);

			System.out.println("id="+doc.get("id")+",name=" + doc.get("name") + ",content=" + doc.get("content"));
		}
	}

今天就到这里

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值