该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-01-05
细粒度分词,很是钦佩。能有最新的源代码吗?
|
|
返回顶楼 | |
发表时间:2010-01-05
Rexwong 写道 细粒度分词,很是钦佩。能有最新的源代码吗?
有啊,开源当然有源码啊。google code地址上去就有了,可以使用svn,也有打包好的。 |
|
返回顶楼 | |
发表时间:2010-01-06
最后修改:2010-01-06
linliangyi2007 写道 引用 请教一个问题,比如我对一个字符串 "硬盘驱动器" 做索引了以后, 搜索 "硬" 或者 "盘" 都不能搜索到,但是如果搜索"硬盘"就可以,这是什么问题呢?
lucene是按照分词切分的结果进行完整匹配查询的, "硬盘驱动器"被切分成“硬盘”“驱动”“驱动器”,但没有“硬" 和 "盘",(那样是单字切分),因此搜索不到,这个是lucene的基础概念,切记。 要是今年多了一个新词叫“盘驱”,明年多了一个新词叫“动器”,怎么办? 如果客户强烈要求搜“硬”时能搜到记录,怎么办? |
|
返回顶楼 | |
发表时间:2010-01-06
fuwang 写道 linliangyi2007 写道 引用 请教一个问题,比如我对一个字符串 "硬盘驱动器" 做索引了以后, 搜索 "硬" 或者 "盘" 都不能搜索到,但是如果搜索"硬盘"就可以,这是什么问题呢?
lucene是按照分词切分的结果进行完整匹配查询的, "硬盘驱动器"被切分成“硬盘”“驱动”“驱动器”,但没有“硬" 和 "盘",(那样是单字切分),因此搜索不到,这个是lucene的基础概念,切记。 要是今年多了一个新词叫“盘驱”,明年多了一个新词叫“动器”,怎么办? 如果客户强烈要求搜“硬”时能搜到记录,怎么办? 我觉得你这个需求是为杜撰而杜撰的,首先就与中文的特性违背了。每种语言都有它的切分特性,英文是通过空格分隔,而中文的特性我们采用了词库。这就意味着当“硬盘”是一个词语的时候,“硬”与“硬盘”在词义上是毫无关系的。分词器只可能尽可能适应于中文的常规语法切分,而不可能你想怎么分就怎么分。 lucene索引的特性也决定了它的最高效率是“完全索引匹配”,当然你可以使用“前缀匹配”,但这个与lucene的倒排索引设计理念是背道而驰的。 |
|
返回顶楼 | |
发表时间:2010-01-06
linliangyi2007 写道 Rexwong 写道 细粒度分词,很是钦佩。能有最新的源代码吗?
有啊,开源当然有源码啊。google code地址上去就有了,可以使用svn,也有打包好的。 晕了,在你的blog里下了个rar,没有源码,就没去code Google看看。懒了,懒了 另外,请教一下,在“神话电视连续剧”搜“神话电视”没有搜到。“神话电视”应该是切成“神话”“电视”了。导致这个结果是个什么原因呢? |
|
返回顶楼 | |
发表时间:2010-01-06
Rexwong 写道 linliangyi2007 写道 Rexwong 写道 细粒度分词,很是钦佩。能有最新的源代码吗?
有啊,开源当然有源码啊。google code地址上去就有了,可以使用svn,也有打包好的。 晕了,在你的blog里下了个rar,没有源码,就没去code Google看看。懒了,懒了 另外,请教一下,在“神话电视连续剧”搜“神话电视”没有搜到。“神话电视”应该是切成“神话”“电视”了。导致这个结果是个什么原因呢? 有一种可能,你的Analyzer设置成最大切分模式,“神话电视连续剧”可能被切分为 神话电视连续剧 0-2 : 神话 : CJK_NORMAL 2-7 : 电视连续剧 : CJK_NORMAL 这样你使用“神话“and”电视”搜索就搜不到,请使用IKAnalyzer默认的构造函数,或者IKAnalyzer(false),这样的切分结果是 神话电视连续剧 0-2 : 神话 : CJK_NORMAL 2-7 : 电视连续剧 : CJK_NORMAL 2-4 : 电视 : CJK_NORMAL 4-7 : 连续剧 : CJK_NORMAL 4-6 : 连续 : CJK_NORMAL |
|
返回顶楼 | |
发表时间:2010-01-11
楼主,我想问下,对于数据冗余是怎么处理的?
例如: 我对数据库一张表的每个字段都建立了索引,但我搜索的时候,不想针对一个字段就行搜索,是在所有字段中搜索, 这样搜索出来的结果就会出现冗余,数据库一条记录可能会被搜索到多次 我想问的是,有什么办法能过滤这些冗余的数据 例如: 在检搜索引1中搜索到了数据2(索引1中存在数据2中一个字段的索引),那么在检搜索引2的时候就过滤掉数据2(索引2中存在数据2中一个字段的索引),不对数据2进行搜索 |
|
返回顶楼 | |
发表时间:2010-01-11
swprogrammer 写道 楼主,我想问下,对于数据冗余是怎么处理的?
例如: 我对数据库一张表的每个字段都建立了索引,但我搜索的时候,不想针对一个字段就行搜索,是在所有字段中搜索, 这样搜索出来的结果就会出现冗余,数据库一条记录可能会被搜索到多次 我想问的是,有什么办法能过滤这些冗余的数据 例如: 在检搜索引1中搜索到了数据2(索引1中存在数据2中一个字段的索引),那么在检搜索引2的时候就过滤掉数据2(索引2中存在数据2中一个字段的索引),不对数据2进行搜索 你说的是数据库中才会有这个问题的,Lucene本身就是全文搜索(全字段搜索)的,不会出现结果重复。 |
|
返回顶楼 | |
发表时间:2010-01-12
package lucene.database; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.wltea.analyzer.lucene.IKAnalyzer; import org.wltea.analyzer.lucene.IKQueryParser; import org.wltea.analyzer.lucene.IKSimilarity; public class LuceneDemo { // 索引存放目录 private String directory = "d:/index/"; //根据哪个字段去查询 public String searchField = ""; //搜索相似度最高的几条记录 public int n = 5; public LuceneDemo(String searchField, int n) { this.searchField = searchField; this.n = n; } /** * 查询数据并创建索引 * * @param rs * 数据集 */ public void Index(ResultSet rs) { try { IndexWriter writer = new IndexWriter(directory, getAnalyzer(), true); int mergeFactor = 1000; int maxMergeDocs = Integer.MAX_VALUE; writer.setMergeFactor(mergeFactor); writer.setMaxMergeDocs(maxMergeDocs); while (rs.next()) { Document doc = new Document(); doc.add(new Field("id", rs.getString("au_id"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("name", rs.getString("au_name"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("phone", rs.getString("phone"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("address", rs.getString("address"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("City", rs.getString("city"), Field.Store.YES, Field.Index.ANALYZED)); writer.addDocument(doc); } writer.optimize(); writer.close(); } catch (IOException e) { System.out.println(e); } catch (SQLException e) { System.out.println(e); } } public TopDocs seacher(String queryString) { TopDocs topDocs = null; try { //使用IKQueryParser查询分析器构造Query对象 Query query = IKQueryParser.parse("city", queryString); if(searchField != null && !"".equals(searchField)) { query = IKQueryParser.parse("city", queryString); }else { query = IKQueryParser.parseMultiField(new String[]{"id","name","phone","address","City"}, queryString); } //搜索相似度最高的5条记录 topDocs = getIndexSearcher().search(query , n); } catch (Exception e) { System.out.print(e); } return topDocs; } /** * 获取分词器 * * @return 分词器 */ public Analyzer getAnalyzer() { // 创建中文分词器并返回 return new IKAnalyzer(); } /** * 获取搜索器 * @return 搜索器 * @throws CorruptIndexException * @throws IOException */ public IndexSearcher getIndexSearcher() throws CorruptIndexException, IOException { //实例化搜索器 IndexSearcher isearcher = new IndexSearcher(directory); //在索引器中使用IKSimilarity相似度评估器 isearcher.setSimilarity(new IKSimilarity()); return isearcher; } } package lucene.database; import java.io.IOException; import java.util.Date; import org.apache.lucene.document.Document; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; public class Test { public static void main(String[] args) throws CorruptIndexException, IOException { DatabaseLuceneDemo dld = new DatabaseLuceneDemo(); Date start = new Date(); LuceneDemo luceneDemo = new LuceneDemo("", 5); luceneDemo.Index(dld.query("select * from Authors")); TopDocs topDocs = luceneDemo.seacher("023"); Date end = new Date(); System.out.println(end.getTime() - start.getTime()); System.out.println("命中:" + topDocs.totalHits); //结果 ScoreDoc[] scoreDocs = topDocs.scoreDocs; //获取查询分析器 IndexSearcher isearcher = luceneDemo.getIndexSearcher(); for (int i = 0; i < topDocs.totalHits; i++){ Document targetDoc = isearcher.doc(scoreDocs[i].doc); //targetDoc.getField("id").setValue("fdafdf"); System.out.println("内容:" + targetDoc.get("id") + " " + targetDoc.get("name") + " " + targetDoc.get("phone") + " " + targetDoc.get("address") + " " + targetDoc.get("City")); } } } 结果: 2172 命中:996 内容:1 周海诺 023-88888888 11111 aaaa 内容:3 彭珊珊 023-88833338 3333 cccc 内容:4 刘敏 023-88899999 4444 dddd 内容:9 999 023-99999999 9999 99999 内容:9 999 023-99999999 9999 99999 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at lucene.database.Test.main(Test.java:33) 这里还有个下标越界错误,这个我能搞懂, 但这个冗余是能过滤吗?怎么过滤? |
|
返回顶楼 | |
发表时间:2010-01-12
swprogrammer 写道 package lucene.database; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.wltea.analyzer.lucene.IKAnalyzer; import org.wltea.analyzer.lucene.IKQueryParser; import org.wltea.analyzer.lucene.IKSimilarity; public class LuceneDemo { // 索引存放目录 private String directory = "d:/index/"; //根据哪个字段去查询 public String searchField = ""; //搜索相似度最高的几条记录 public int n = 5; public LuceneDemo(String searchField, int n) { this.searchField = searchField; this.n = n; } /** * 查询数据并创建索引 * * @param rs * 数据集 */ public void Index(ResultSet rs) { try { IndexWriter writer = new IndexWriter(directory, getAnalyzer(), true); int mergeFactor = 1000; int maxMergeDocs = Integer.MAX_VALUE; writer.setMergeFactor(mergeFactor); writer.setMaxMergeDocs(maxMergeDocs); while (rs.next()) { Document doc = new Document(); doc.add(new Field("id", rs.getString("au_id"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("name", rs.getString("au_name"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("phone", rs.getString("phone"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("address", rs.getString("address"), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("City", rs.getString("city"), Field.Store.YES, Field.Index.ANALYZED)); writer.addDocument(doc); } writer.optimize(); writer.close(); } catch (IOException e) { System.out.println(e); } catch (SQLException e) { System.out.println(e); } } public TopDocs seacher(String queryString) { TopDocs topDocs = null; try { //使用IKQueryParser查询分析器构造Query对象 Query query = IKQueryParser.parse("city", queryString); if(searchField != null && !"".equals(searchField)) { query = IKQueryParser.parse("city", queryString); }else { query = IKQueryParser.parseMultiField(new String[]{"id","name","phone","address","City"}, queryString); } //搜索相似度最高的5条记录 topDocs = getIndexSearcher().search(query , n); } catch (Exception e) { System.out.print(e); } return topDocs; } /** * 获取分词器 * * @return 分词器 */ public Analyzer getAnalyzer() { // 创建中文分词器并返回 return new IKAnalyzer(); } /** * 获取搜索器 * @return 搜索器 * @throws CorruptIndexException * @throws IOException */ public IndexSearcher getIndexSearcher() throws CorruptIndexException, IOException { //实例化搜索器 IndexSearcher isearcher = new IndexSearcher(directory); //在索引器中使用IKSimilarity相似度评估器 isearcher.setSimilarity(new IKSimilarity()); return isearcher; } } package lucene.database; import java.io.IOException; import java.util.Date; import org.apache.lucene.document.Document; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; public class Test { public static void main(String[] args) throws CorruptIndexException, IOException { DatabaseLuceneDemo dld = new DatabaseLuceneDemo(); Date start = new Date(); LuceneDemo luceneDemo = new LuceneDemo("", 5); luceneDemo.Index(dld.query("select * from Authors")); TopDocs topDocs = luceneDemo.seacher("023"); Date end = new Date(); System.out.println(end.getTime() - start.getTime()); System.out.println("命中:" + topDocs.totalHits); //结果 ScoreDoc[] scoreDocs = topDocs.scoreDocs; //获取查询分析器 IndexSearcher isearcher = luceneDemo.getIndexSearcher(); for (int i = 0; i < topDocs.totalHits; i++){ Document targetDoc = isearcher.doc(scoreDocs[i].doc); //targetDoc.getField("id").setValue("fdafdf"); System.out.println("内容:" + targetDoc.get("id") + " " + targetDoc.get("name") + " " + targetDoc.get("phone") + " " + targetDoc.get("address") + " " + targetDoc.get("City")); } } } 结果: 2172 命中:996 内容:1 周海诺 023-88888888 11111 aaaa 内容:3 彭珊珊 023-88833338 3333 cccc 内容:4 刘敏 023-88899999 4444 dddd 内容:9 999 023-99999999 9999 99999 内容:9 999 023-99999999 9999 99999 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at lucene.database.Test.main(Test.java:33) 这里还有个下标越界错误,这个我能搞懂, 但这个冗余是能过滤吗?怎么过滤? 哥哥,这个就是你取索引的方法有问题了啊。我不是很清楚你对结果的查询要求,所以没法给你完整的建议。但从分词器的角度上说,它已经圆满完成任务了。 |
|
返回顶楼 | |