lucene(18)—lucene索引时join和查询时join使用示例
了解sql的朋友都知道,我们在查询的时候可以采用join查询,即对有一定关联关系的对象进行联合查询来对多维的数据进行整理。这个联合查询的方式挺方便的,跟我们现实生活中的托人找关系类似,我们想要完成一件事,先找自己的熟人,然后通过熟人在一次找到其他,最终通过这种手段找到想要联系到的人。有点类似于”世间万物皆有联系“的感觉。
lucene的join包提供了索引时join和查询时join的功能;
Index-time join
大意是索引时join提供了查询时join的支持,且IndexWriter.addDocuments()方法调用时被join的documents以单个document块存储索引。索引时join对普通文本内容(如xml文档或数据库表)是方便可用的。特别是对类似于数据库的那种多表关联的情况,我们需要对提供关联关系的列提供join支持;
在索引时join的时候,索引中的documents被分割成parent documents(每个索引块的最后一个document)和child documents (除了parent documents外的所有documents). 由于lucene并不记录doc块的信息,我们需要提供一个Filter来标示parent documents。
在搜索结果的时候,我们利用ToParentBlockJoinQuery来从child query到parent document space来remap/join对应的结果。
如果我们只关注匹配查询条件的parent documents,我们可以用任意的collector来采集匹配到的parent documents;如果我们还想采集匹配parent document查询条件的child documents,我们就需要利用ToParentBlockJoinCollector来进行查询;一旦查询完成,我们可以利用ToParentBlockJoinCollector.getTopGroups()来获取匹配条件的TopGroups.
Query-time joins
查询时join是基于索引词,其实现有两步:
- 第一步先从匹配fromQuery的fromField中采集所有的数据;
- 从第一步得到的数据中筛选出所有符合条件的documents
查询时join接收一下输入参数:
- fromField:fromField的名称,即要join的documents中的字段;
- formQuery: 用户的查询条件
- multipleValuesPerDocument: fromField在document是否是多个值
- scoreMode:定义other join side中score是如何被使用的。如果不关注scoring,我们只需要设置成ScoreMode.None,此种方式会忽略评分因此会更高效和节约内存;
- toField:toField的名称,即要join的toField的在对应的document中的字段
通常查询时join的实现类似于如下:
|
|
查询示例
这里我们模拟6组数据,示例代码如下
|
|
程序的运行结果如下:
|
|
以第一个查询为例:
我们在查询的时候先根据name=name2这个查询条件找到记录为doc3的document,由于查询的是toField匹配的,我们在根据doc3找到其toField的值为4,然后查询条件变为productId:4,找出除本条记录外的其他数据,结果正好为3,符合条件。