创建lucene时document字段属性的选择
转载请注明出处:http://xiaojimanman.iteye.com/admin/blogs/1972715
在创建索引文件的时候,不知道会不会有下面的疑惑:
1)document字段设置成什么类型?
2)采用什么分词器?
3)字段的权重设置成多少等?
这些也许都是我们在创建索引文件中经常会遇到的问题,这篇就主要说一下自己关于第一个问题的理解
此篇是以 lucene 4.3.1 为事例,其他版本类似:
个人认为,我们在创建Document对象的时候,对于以后可能用于用户搜索的字段,我们在创建索引的时候必须对该字段值进行分词处理;对于那些只做存储的字段,就可以只简单的保存一下即可,不需要分词,也不需要检索;对于那些需要整体考虑字段,就不能采取分词。下面就简单的看下Document的API:
对于那种已经有明确的类型的字段可以设置成 IntField、FloatField、LongField等,这种字段类型就像API中说的一样,可以高效的处理过滤和排序。如果索引文件中,某些字段是用来排序或者索引的,那这种类型应该是不错的选择。StringField 是将属性值当做一个整体,并不对其做分词操作,但是可以做检索。StoredField 只是将属性值做简单的存储,并不参与搜索、过滤和排序等操作,只是在查询索引时能通过IndexSearcher.doc(int) 或 IndexReader.document(int, org.apache.lucene.index.StoredFieldVisitor) 取得对应的字段值。TextField 类型主要用于根据用户输入词进行搜索的字段,这里就牵扯到分词器的选择。
这里就简单的说一下自己对分词器选择的理解。选择何种分词器用户的搜索效果才更好,这个主要根据产品的特点(也许有人会说,这不等于白说嘛)。举个简单的例子:前几天自己给人民网新闻和论坛做了一个站内搜索,对于新闻这种信息的搜索,个人理解最大的就是对人名或者事件的搜索,如果分词器可以准确的处理出人名,那对搜索结果应该会有很大的提升,但是现在主流的几个分词器都没有关于人名的处理或者没有全面的处理,所以自己只能去修改IKAnalyzer分词器,让其可以准确的处理人名。这样,用户搜索出的结果质量就有很大的提高(和IKAnalyzer分词器相比),也就是说要根据自己产品的特点去选择或者修改现有的分词器。最后说一个,在创建索引和对用户搜索词分词的时候,尽量使用同一个分词器。
下面就举一个简单的实例:
/** *@Description: Document与各个类(数据结构)之间的转换 */ package cn.yicha.novel.search.util; import org.apache.lucene.document.Document; import org.apache.lucene.document.IntField; import org.apache.lucene.document.StoredField; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.document.Field.Store; import cn.yicha.novel.search.model.NovelIndex; public class ParseDocument { /** * @param novelIndex * @return Document * @Date: 2013-11-1 * @Author: lulei * @Description: 将NovelIndex对象转化为Document对象,如果NovelIndex为空或者不全,直接返回null */ public static Document parseNovelIndexToDocument(NovelIndex novelIndex){ if (novelIndex == null || !novelIndex.isFull()){ return null; } Document doc = new Document(); //StoredField if (novelIndex.getSourceSite() != null) { doc.add(new StoredField("sourceSite", novelIndex.getSourceSite())); } if (novelIndex.getChapterList() != null) { doc.add(new StoredField("chapterList", novelIndex.getChapterList())); } //StringField if (novelIndex.getUpdateTime() != null) { doc.add(new StringField("updateTime", novelIndex.getUpdateTime(), Store.YES)); } if (novelIndex.getAuthor() != null) { doc.add(new StringField("author", novelIndex.getAuthor(), Store.YES)); } if (novelIndex.getName() != null) { doc.add(new StringField("name", novelIndex.getName(), Store.YES)); } if (novelIndex.getType() != null) { doc.add(new StringField("type", novelIndex.getType(), Store.YES)); } if (novelIndex.getNid() != null) { doc.add(new StringField("nid", novelIndex.getNid(), Store.YES)); } //IntField if (novelIndex.getChapterCount() != -1) { doc.add(new IntField("chapterCount", novelIndex.getChapterCount(), Store.YES)); } if (novelIndex.getState() != -1) { doc.add(new IntField("state", novelIndex.getState(), Store.YES)); } //TextField if (novelIndex.getDescription() != null) { doc.add(new TextField("description", novelIndex.getDescription(), Store.YES)); } if (novelIndex.getKeyWords() != null) { TextField keyWords = new TextField("keyWords", novelIndex.getKeyWords(), Store.YES); keyWords.setBoost(1.5f); doc.add(keyWords); } return doc; } }
这就是自己现在测试项目中的一个用到的一个具体实例,当然细节还有待进一步的验证与调整。
具体的业务就只对 keyWords 和 description 这两个字段做分词搜索,所以也就只有这两个字段采用 TextFiled 类型,其他字段都根据具体的业务选择了对应的类型。
上一篇: highcharts 时间少8小时问题
下一篇: 处理字符串的好方法,该怎么解决