了解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的实现类似于例如以下:

  1. String fromField = "from"; // Name of the from field
  2. boolean multipleValuesPerDocument = false; // Set only yo true in the case when your fromField has multiple values per document in your index
  3. String toField = "to"; // Name of the to field
  4. ScoreMode scoreMode = ScoreMode.Max // Defines how the scores are translated into the other side of the join.
  5. Query fromQuery = new TermQuery(new Term("content", searchTerm)); // Query executed to collect from values to join to the to values
  6.  
  7. Query joinQuery = JoinUtil.createJoinQuery(fromField, multipleValuesPerDocument, toField, fromQuery, fromSearcher, scoreMode);
  8. TopDocs topDocs = toSearcher.search(joinQuery, 10); // Note: toSearcher can be the same as the fromSearcher
  9. // Render topDocs...

查询演示样例

这里我们模拟6组数据。演示样例代码例如以下

  1. package com.lucene.index.test;
  2.  
  3. import static org.junit.Assert.assertEquals;
  4.  
  5. import java.nio.file.Paths;
  6.  
  7. import org.apache.lucene.analysis.Analyzer;
  8. import org.apache.lucene.analysis.standard.StandardAnalyzer;
  9. import org.apache.lucene.document.Document;
  10. import org.apache.lucene.document.Field;
  11. import org.apache.lucene.document.SortedDocValuesField;
  12. import org.apache.lucene.document.TextField;
  13. import org.apache.lucene.index.DirectoryReader;
  14. import org.apache.lucene.index.IndexReader;
  15. import org.apache.lucene.index.IndexWriter;
  16. import org.apache.lucene.index.IndexWriterConfig;
  17. import org.apache.lucene.index.IndexWriterConfig.OpenMode;
  18. import org.apache.lucene.index.Term;
  19. import org.apache.lucene.search.IndexSearcher;
  20. import org.apache.lucene.search.Query;
  21. import org.apache.lucene.search.TermQuery;
  22. import org.apache.lucene.search.TopDocs;
  23. import org.apache.lucene.search.join.JoinUtil;
  24. import org.apache.lucene.search.join.ScoreMode;
  25. import org.apache.lucene.store.Directory;
  26. import org.apache.lucene.store.FSDirectory;
  27. import org.apache.lucene.util.BytesRef;
  28. import org.junit.Test;
  29.  
  30. public class TestJoin {
  31. @Test
  32. public void testSimple() throws Exception {
  33. final String idField = "id";
  34. final String toField = "productId";
  35.  
  36. Directory dir = FSDirectory.open(Paths.get("index"));
  37. Analyzer analyzer = new StandardAnalyzer();
  38. IndexWriterConfig config = new IndexWriterConfig(analyzer);
  39. config.setOpenMode(OpenMode.CREATE);
  40. IndexWriter w = new IndexWriter(dir, config);
  41.  
  42. // 0
  43. Document doc = new Document();
  44. doc.add(new TextField("description", "random text", Field.Store.YES));
  45. doc.add(new TextField("name", "name1", Field.Store.YES));
  46. doc.add(new TextField(idField, "1", Field.Store.YES));
  47. doc.add(new SortedDocValuesField(idField, new BytesRef("1")));
  48.  
  49. w.addDocument(doc);
  50.  
  51. // 1
  52. Document doc1 = new Document();
  53. doc1.add(new TextField("price", "10.0", Field.Store.YES));
  54. doc1.add(new TextField(idField, "2", Field.Store.YES));
  55. doc1.add(new SortedDocValuesField(idField, new BytesRef("2")));
  56. doc1.add(new TextField(toField, "1", Field.Store.YES));
  57. doc1.add(new SortedDocValuesField(toField, new BytesRef("1")));
  58.  
  59. w.addDocument(doc1);
  60.  
  61. // 2
  62. Document doc2 = new Document();
  63. doc2.add(new TextField("price", "20.0", Field.Store.YES));
  64. doc2.add(new TextField(idField, "3", Field.Store.YES));
  65. doc2.add(new SortedDocValuesField(idField, new BytesRef("3")));
  66. doc2.add(new TextField(toField, "1", Field.Store.YES));
  67. doc2.add(new SortedDocValuesField(toField, new BytesRef("1")));
  68.  
  69. w.addDocument(doc2);
  70.  
  71. // 3
  72. Document doc3 = new Document();
  73. doc3.add(new TextField("description", "more random text", Field.Store.YES));
  74. doc3.add(new TextField("name", "name2", Field.Store.YES));
  75. doc3.add(new TextField(idField, "4", Field.Store.YES));
  76. doc3.add(new SortedDocValuesField(idField, new BytesRef("4")));
  77.  
  78. w.addDocument(doc3);
  79.  
  80. // 4
  81. Document doc4 = new Document();
  82. doc4.add(new TextField("price", "10.0", Field.Store.YES));
  83. doc4.add(new TextField(idField, "5", Field.Store.YES));
  84. doc4.add(new SortedDocValuesField(idField, new BytesRef("5")));
  85. doc4.add(new TextField(toField, "4", Field.Store.YES));
  86. doc4.add(new SortedDocValuesField(toField, new BytesRef("4")));
  87. w.addDocument(doc4);
  88.  
  89. // 5
  90. Document doc5 = new Document();
  91. doc5.add(new TextField("price", "20.0", Field.Store.YES));
  92. doc5.add(new TextField(idField, "6", Field.Store.YES));
  93. doc5.add(new SortedDocValuesField(idField, new BytesRef("6")));
  94. doc5.add(new TextField(toField, "4", Field.Store.YES));
  95. doc5.add(new SortedDocValuesField(toField, new BytesRef("4")));
  96. w.addDocument(doc5);
  97.  
  98. //6
  99. Document doc6 = new Document();
  100. doc6.add(new TextField(toField, "4", Field.Store.YES));
  101. doc6.add(new SortedDocValuesField(toField, new BytesRef("4")));
  102. w.addDocument(doc6);
  103. w.commit();
  104. w.close();
  105. IndexReader reader = DirectoryReader.open(dir);
  106. IndexSearcher indexSearcher = new IndexSearcher(reader);
  107.  
  108. // Search for product
  109. Query joinQuery = JoinUtil.createJoinQuery(idField, false, toField, new TermQuery(new Term("name", "name2")), indexSearcher, ScoreMode.None);
  110. System.out.println(joinQuery);
  111. TopDocs result = indexSearcher.search(joinQuery, 10);
  112. System.out.println("查询到的匹配数据:"+result.totalHits);
  113.  
  114. joinQuery = JoinUtil.createJoinQuery(idField, false, toField, new TermQuery(new Term("name", "name1")), indexSearcher, ScoreMode.None);
  115. result = indexSearcher.search(joinQuery, 10);
  116. System.out.println("查询到的匹配数据:"+result.totalHits);
  117. // Search for offer
  118. joinQuery = JoinUtil.createJoinQuery(toField, false, idField, new TermQuery(new Term("id", "5")), indexSearcher, ScoreMode.None);
  119. result = indexSearcher.search(joinQuery, 10);
  120. System.out.println("查询到的匹配数据:"+result.totalHits);
  121.  
  122. indexSearcher.getIndexReader().close();
  123. dir.close();
  124. }
  125.  
  126. }

程序的执行结果例如以下:

  1. 查询到的匹配数据:3
  2. 查询到的匹配数据:2
  3. 查询到的匹配数据:1

以第一个查询为例:

我们在查询的时候先依据name=name2这个查询条件找到记录为doc3的document,因为查询的是toField匹配的,我们在依据doc3找到其toField的值为4,然后查询条件变为productId:4,找出除本条记录外的其它数据。结果正好为3。符合条件。

一步一步跟我学习lucene是对最近做lucene索引的总结,大家有问题的话联系本人的Q-Q:  891922381,同一时候本人新建Q-Q群:106570134(lucene,solr,netty,hadoop)。大家共同探讨,本人争取每日一博。希望大家持续关注,会带给大家惊喜的



一步一步跟我学习lucene(18)---lucene索引时join和查询时join使用演示样例的更多相关文章

  1. 模式识别 - 处理多演示样例学习(MIL)特征(matlab)

    处理多演示样例学习(MIL)特征(matlab) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27206325 多演示样例学习( ...

  2. Tuxedo安装、配置、以及演示样例程序 (学习网址)

    Tuxedo安装.配置.以及演示样例程序 (学习网址): 1.http://liu9403.iteye.com/blog/1415684 2.http://www.cnblogs.com/fnng/a ...

  3. openWRT学习之LUCI之中的一个helloworld演示样例

    备注1:本文 讲述的是原生的openWRT环境下的LUCI 备注2:本文參考了诸多资料.感谢网友分享.參考资料: http://www.cnblogs.com/zmkeil/archive/2013/ ...

  4. Libevent 学习笔记 (1)——Libevent 2.0安装与简单演示样例

    今天開始学习Libevent . Libevent 是开源社区的一款高性能I/O框架库. 主要特点有: 1 跨平台. 2 统一事件源 3 线程安全 4 基于Reactor 今天主要进行了Libeven ...

  5. c语言学习之结构篇代码演示样例-输入n个同学的姓名,数学英语成绩,依照平均分从低到高排序并输出

    #include<stdio.h> void main(){ const int count = 5;//定义数量 struct student{ char name[80]; float ...

  6. 【OpenGL 学习笔记01】HelloWorld演示样例

    <<OpenGL Programming Guide>>这本书是看了忘,忘了又看,赶脚还是把笔记做一做心里比較踏实,哈哈. 我的主题是,好记性不如烂笔头. ========== ...

  7. Solr 6.7学习笔记(03)-- 样例配置文件 solrconfig.xml

    位于:${solr.home}\example\techproducts\solr\techproducts\conf\solrconfig.xml <?xml version="1. ...

  8. 一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

    这两天加班,不能兼顾博客的更新.请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容.而我们又想像数据库那样能直接体如今查询中.这里就是我们所说的增量索引.对于这种需求我们怎么来实现呢?lu ...

  9. 12.Linux软件安装 (一步一步学习大数据系列之 Linux)

    1.如何上传安装包到服务器 有三种方式: 1.1使用图形化工具,如: filezilla 如何使用FileZilla上传和下载文件 1.2使用 sftp 工具: 在 windows下使用CRT 软件 ...

随机推荐

  1. php解析 html类库 simple_html_dom

    如果从字符串加载html文档,需要先从网络上下载.建议使用cURL来抓取html文档并加载DOM中. 查找html元素 可以使用find函数来查找html文档中的元素.返回的结果是一个包含了对象的数组 ...

  2. linux下常用命令失效

    注意:修改一下PATH环境变量 export PATH=/bin:/usr/bin/:. 可以把这句话加到你的.profile或者.bash_profile里,这样每次登录的时候都会生效

  3. Visual C++6.0的下载与安装

    1.Visual C++6.0的下载 本书中使用的Visual C++6.0的中文版,读者可以在网上搜索,下载合适的安装包. 2.Visual C++6.0的安装 Visual C++6.0的具体安装 ...

  4. 查看 Android App 的 versionCode

    有 App 源码时,可以直接查看 AndroidManifest.xml 文件. <manifest android:versionName="1.4" android:ve ...

  5. 看懂SqlServer执行计划

    在园子看到一篇SQLServer关于查询计划的好文,激动啊,特转载.原文出自:http://www.cnblogs.com/fish-li/archive/2011/06/06/2073626.htm ...

  6. 工作中总结的经验之git篇

    不要以为你会git,你要知道,git不是只有commit和push 由于系统分析与设计的期末Project需要团队合作开发,因此在这里想谈谈GitHub团队项目合作开发的流程: 项目创建 项目负责人在 ...

  7. BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树

    Code: #include<bits/stdc++.h> #define maxn 200003 #define inf -1000000 using namespace std; vo ...

  8. PAT_A1021#Deepest Root

    Source: PAT A1021 Deepest Root (25 分) Description: A graph which is connected and acyclic can be con ...

  9. Python 切片 day3

    你可以处理列表的部分元素——Python称之为切片 . 一.使用方法: 要创建切片,可指定要使用的第一个元素和最后一个元素的索引. 与函数range() 一样,Python在到达你指定的第二个索引前面 ...

  10. github+hexo(window10)

    一.申请github账户 二.先安装node.js.git 本地: 三.安装hexo(建立静态网页,用Markdown写博客) 1.创建文件地址 在合适的地方新建一个文件夹,用来存放自己的博客文件,比 ...