设为首页 收藏本站
查看: 1197|回复: 0

[经验分享] Lucene/Solr(5.0) 源码初探- Lucene Facet SortedSetDocValues (一)

[复制链接]

尚未签到

发表于 2016-12-17 06:18:42 | 显示全部楼层 |阅读模式
最近研究lucene 5.0 源码, 有点心得,记在此处以免忘却。查过资料lucene4.0+全面 升级了对facet的功能效率问题,其一直宣传的一点是用DocValues改进和应用,DocValues主要是在正向索引中为每个文档存储相应的需要facet 的 field的值(配以相应的存储格式和压缩算法)来改变其效率,在本文中先用 SortedSetDocValues 做为研究例子,同时用lucene自带的例子开头:

public class SimpleSortedSetFacetsExample {
/*这里例子原来是讲index文件放在内存中,本人为了查看文件格式将其放在指定目录里   面*/
private Directory indexDir = null;//new RAMDirectory();
private final FacetsConfig config = new FacetsConfig();
/** Empty constructor */
public SimpleSortedSetFacetsExample() {
try {
indexDir = FSDirectory.open(Paths.get("D:\\index"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/** Build the example index. */
private void index() throws IOException {
IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(
new WhitespaceAnalyzer()).setOpenMode(OpenMode.CREATE));
Document doc = new Document();
// 这里保存文件格式用的是专门SortedSetDocValuesFacetField field,4.0+支持
doc.add(new SortedSetDocValuesFacetField("Author", "Bob"));
doc.add(new SortedSetDocValuesFacetField("Publish Year", "2010"));
//在build方法里面开始组织field信息,见code1:
indexWriter.addDocument(config.build(doc));
doc = new Document();
doc.add(new SortedSetDocValuesFacetField("Author", "Lisa"));
doc.add(new SortedSetDocValuesFacetField("Publish Year", "2010"));
indexWriter.addDocument(config.build(doc));
doc = new Document();
doc.add(new SortedSetDocValuesFacetField("Author", "Lisa"));
doc.add(new SortedSetDocValuesFacetField("Publish Year", "2012"));
indexWriter.addDocument(config.build(doc));
doc = new Document();
doc.add(new SortedSetDocValuesFacetField("Author", "Susan"));
doc.add(new SortedSetDocValuesFacetField("Publish Year", "2012"));
indexWriter.addDocument(config.build(doc));
doc = new Document();
doc.add(new SortedSetDocValuesFacetField("Author", "Frank"));
doc.add(new SortedSetDocValuesFacetField("Publish Year", "1999"));
indexWriter.addDocument(config.build(doc));
indexWriter.close();
}
/** User runs a query and counts facets. */
private List<FacetResult> search() throws IOException {
DirectoryReader indexReader = DirectoryReader.open(indexDir);
IndexSearcher searcher = new IndexSearcher(indexReader);
SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(indexReader);
// Aggregatses the facet counts
FacetsCollector fc = new FacetsCollector();
// MatchAllDocsQuery is for "browsing" (counts facets
// for all non-deleted docs in the index); normally
// you'd use a "normal" query:
FacetsCollector.search(searcher, new MatchAllDocsQuery(), 10, fc);
// Retrieve results
Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
List<FacetResult> results = new ArrayList<>();
results.add(facets.getTopChildren(10, "Author"));
results.add(facets.getTopChildren(10, "Publish Year"));
//在这里触发flush 操作
indexReader.close();
return results;
}
/** User drills down on 'Publish Year/2010'. */
private FacetResult drillDown() throws IOException {
DirectoryReader indexReader = DirectoryReader.open(indexDir);
IndexSearcher searcher = new IndexSearcher(indexReader);
SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(indexReader);
// Now user drills down on Publish Year/2010:
DrillDownQuery q = new DrillDownQuery(config);
q.add("Publish Year", "2010");
FacetsCollector fc = new FacetsCollector();
FacetsCollector.search(searcher, q, 10, fc);
// Retrieve results
Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
FacetResult result = facets.getTopChildren(10, "Author");
indexReader.close();
return result;
}
/** Runs the search example. */
public List<FacetResult> runSearch() throws IOException {
index();
return search();
}
/** Runs the drill-down example. */
public FacetResult runDrillDown() throws IOException {
index();
return drillDown();
}
/** Runs the search and drill-down examples and prints the results. */
public static void main(String[] args) throws Exception {
System.out.println("Facet counting example:");
System.out.println("-----------------------");
SimpleSortedSetFacetsExample example = new SimpleSortedSetFacetsExample();
List<FacetResult> results = example.runSearch();
System.out.println("Author: " + results.get(0));
System.out.println("Publish Year: " + results.get(0));
System.out.println("\n");
System.out.println("Facet drill-down example (Publish Year/2010):");
System.out.println("---------------------------------------------");
System.out.println("Author: " + example.runDrillDown());
}
}


code1:

//FacetsConfig.build
public Document build(TaxonomyWriter taxoWriter, Document doc) throws IOException {
......
//组织SortedSetDocValuesFacetField 信息
if (field.fieldType() == SortedSetDocValuesFacetField.TYPE) {
SortedSetDocValuesFacetField facetField = (SortedSetDocValuesFacetField) field;
FacetsConfig.DimConfig dimConfig = getDimConfig(facetField.dim);
if (dimConfig.multiValued == false) {
checkSeen(seenDims, facetField.dim);
}
/**这里做了统一处理,对于所有的 SortedSetDocValuesFacetField ,其 indexFieldName 统一为$facets,与用户在SortedSetDocValuesFacetField 中定义的完全无关,用户定义的名值对在SortedSetDocValuesFacetField 映射应该是dim,label, 如new SortedSetDocValuesFacetField("Author", "Bob") 那么其dim应该是Author,label是Bob*/
String indexFieldName = dimConfig.indexFieldName;
List<SortedSetDocValuesFacetField> fields = dvByField.get(indexFieldName);
/** fields 这里存储的是 所有的SortedSetDocValuesFacetField , 并且以统一的以indexFieldName 保存在dvByField */
if (fields == null) {
fields = new ArrayList<>();
dvByField.put(indexFieldName, fields);
}
//完成文档的fields的初步处理
fields.add(facetField);
}

.......
processFacetFields(taxoWriter, byField, result);
//这里专门对SortedSetDocValuesFacetField 名值对二次处理,具体见下:
processSSDVFacetFields(dvByField, result);
processAssocFacetFields(taxoWriter, assocByField, result);
............
}

//FacetsConfig.processSSDVFacetFields
private void private void processSSDVFacetFields(Map<String,List<SortedSetDocValuesFacetField>> byField, Document doc) throws IOException {
//System.out.println("process SSDV: " + byField);
for(Map.Entry<String,List<SortedSetDocValuesFacetField>> ent : byField.entrySet()) {
String indexFieldName = ent.getKey();
//System.out.println("  field=" + indexFieldName);
// 循环文档中所有的SortedSetDocValuesFacetField
for(SortedSetDocValuesFacetField facetField : ent.getValue()) {
FacetLabel cp = new FacetLabel(facetField.dim, facetField.label);
/*这里是将fields 中 dim 和 label 连起来中间用"\u001f" 做单元分隔符做区别 , 比如Author\u001fBob*/
String fullPath = pathToString(cp.components, cp.length);
//System.out.println("add " + fullPath);
// For facet counts:
//将整个fullPath 做为值存储。
doc.add(new SortedSetDocValuesField(indexFieldName, new BytesRef(fullPath)));
// For drill-down:
doc.add(new StringField(indexFieldName, fullPath, Field.Store.NO));
doc.add(new StringField(indexFieldName, facetField.dim, Field.Store.NO));
}
}
}


以上完成了SortedSetDocValuesField的一个重组,在分析写进文件系统中,有几个问题先问自己?
上面的代码分析可以看出最后要存储进去的一定是一个dim+label完整的字符串。
1.DocValues 如果是被认为是每个文档的相应的field值,那么存储的时候是按照文档存储的?比如文档1:这个$facets值是E....文档2,这个$facets值 C 存储?那么如果文档间如果有相同的filed值是按照上面重复存储还是只存一个值,如文档1:这个$facets值是E,文档2如果也是相同值E,这个$facets值是存地址?因为A已经存储在文档1中,是否有类似地址指向指向E值?(瞎猜?!),如果按照这样设计文件如何能改善facet统计,这和以前存储又何区别?
2.如果存储不是按照1上面所说的,还有一种方案就是所有的文档在同一个field值给所有文档排序去重共享(SortedSet),那么上面例子存储值就是C,E 对于文档1,2共享,但是这样又带来一个新问题,我必须知道文档1有过什么值,文档2 有过什么值。这又回到1按照文档存储值的老思路上来?!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-315189-1-1.html 上篇帖子: solr-paoding分词-添加自定义词典注意事项 下篇帖子: Lucene/Solr(5.0) 源码初探- Lucene Facet SortedSetDocValues (二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表