Join 加入Lucene

Join 加入Lucene,join,lucene,Join,Lucene,有什么方法可以在Lucene中实现联接吗?Lucene不支持文档之间的关系,但是联接只是括号内多个和的特定组合,但是您需要先将关系展平 示例(SQL=>Lucene): SQL: 卢塞恩: 确保文档上有所有必需字段及其各自的值,如: Customer.Name=>“Customer\u Name”和 Order.Nr=>“Order\u Nr” 然后,查询将是: ( Customer_Name:"SomeName" AND Order_Nr:"400" ) 您可以手动执行通用联接-运行两次搜索

有什么方法可以在Lucene中实现联接吗?

Lucene不支持文档之间的关系,但是联接只是括号内多个
的特定组合,但是您需要先将关系展平

示例(SQL=>Lucene):

SQL:

卢塞恩:
确保文档上有所有必需字段及其各自的值,如: Customer.Name=>“Customer\u Name”和
Order.Nr=>“Order\u Nr”

然后,查询将是:

( Customer_Name:"SomeName" AND Order_Nr:"400" )

您可以手动执行通用联接-运行两次搜索,获取所有结果(而不是前N个), 在联接键上对它们进行排序,并使两个有序列表相交。但这会对你的堆造成很大的冲击(如果这些列表都适合的话)

有可能的优化,但在非常特定的条件下。
也就是说,您进行自连接,只使用(随机访问)
过滤器进行过滤,不使用
查询
。然后,您可以在两个联接字段上手动迭代术语(并行),为每个术语交叉docId列表,过滤它们-这是您的联接

有一种处理简单亲子关系的流行用例的方法,每个文档中的子对象数量相对较少-
与@ntziolis提到的扁平化方法不同,这种方法正确地处理了以下情况:拥有大量简历,每个简历都有多个有工作经验的孩子,并尝试寻找在YYY年在NNN公司工作的人。如果简单地将其展平,您将获得在任何一年为NNN工作的人的简历&在YYY年的某个地方工作过


处理简单的父子案例的另一种方法是平展您的文档,但要确保不同子级的值之间有一个很大的间隔,然后使用
span
query来防止多个子查询在子级之间匹配。有几年前的LinkedIn演示,但我没有找到它。

你也可以使用新的BlockJoinQuery;我在这里的一篇博文中对此进行了描述:


使用joinutil。它允许查询时间连接


请参阅:

在Lucene的顶部有一些实现,可以在几个不同的索引之间实现这种连接。Numere()启用该功能,并使其能够作为RDBMS结果集获取结果。

下面是一个示例

结果:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<DATAPACKET Version="2.0">
  <METADATA>
    <FIELDS>
      <FIELD attrname="type" fieldtype="string" WIDTH="20" />
      <FIELD attrname="category" fieldtype="string" WIDTH="20" />
      <FIELD attrname="sales" fieldtype="i8" />
      <FIELD attrname="total" fieldtype="i4" />
    </FIELDS>
    <PARAMS />
  </METADATA>
  <ROWDATA>
    <ROW type="Book" category="stand" sales="127003304" total="2" />
    <ROW type="Computer" category="eletronic" sales="44765715835" total="896" />
    <ROW type="Meat" category="food" sales="3193526428" total="110" />


。。。继续

稍晚一点,但您可以使用包org.apache.lucene.search.join:

根据他们的文件:

索引加入时间支持在搜索时加入,其中已加入 将文档索引为单个文档块,使用 IndexWriter.addDocuments()


Lucene不是关系数据库。你是什么意思?@skaffman-我使用Lucene作为MS-SQL数据库的全文搜索引擎。我突然想到,如果我只是将所有数据存储在Lucene中的字段中,就可以完全取消SQL DB。然而,要做到这一点,我需要某种方式将文档连接在一起。Norris你不能这样做,你需要将关系扁平化,因为lucene不处理文档之间的关系。据我所知,BlockJoinQuery的问题之一是,当包含的父级或子级之一发生更改时,块需要对块内的元素进行完全重新索引。这正是我希望通过“连接概念”避免的事情。因此,BlockJoinQuery创建了更大的查询灵活性,但没有提供更原子化的存储概念。
select a.type, sum(a.value) as "sales", b.category, count(distinct b.product_id) as "total"
from a (index)
inner join b (index) on (a.seq_id = b.seq_id)
group by a.type, b.category
order by a.type asc, b.category asc


    Join join = RequestFactory.newJoin();

    // inner join a.seq_id = b.seq_id

    join.on("seq_id", Type.INTEGER).equal("seq_id", Type.INTEGER);

    // left
    {
        Request left = join.left();
        left.repository(UtilTest.getPath("indexes/md/master"));
        left.addColumn("type").textType().asc();
        left.addMeasure("value").alias("sales").intType().sum();
    }

    // right
    {
        Request right = join.right();
        right.repository(UtilTest.getPath("indexes/md/detail"));
        right.addColumn("category").textType().asc();
        right.addMeasure("product_id").intType().alias("total").count_distinct();
    }

    Processor processor = ProcessorFactory.newProcessor();
    try {
        ResultPacket result = processor.execute(join);
        System.out.println(result);
    } finally {
        processor.close();
    }
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<DATAPACKET Version="2.0">
  <METADATA>
    <FIELDS>
      <FIELD attrname="type" fieldtype="string" WIDTH="20" />
      <FIELD attrname="category" fieldtype="string" WIDTH="20" />
      <FIELD attrname="sales" fieldtype="i8" />
      <FIELD attrname="total" fieldtype="i4" />
    </FIELDS>
    <PARAMS />
  </METADATA>
  <ROWDATA>
    <ROW type="Book" category="stand" sales="127003304" total="2" />
    <ROW type="Computer" category="eletronic" sales="44765715835" total="896" />
    <ROW type="Meat" category="food" sales="3193526428" total="110" />
   String fromField = "from"; // Name of the from field
   boolean multipleValuesPerDocument = false; // Set only yo true in the case when your fromField has multiple values per document in your index
   String toField = "to"; // Name of the to field
   ScoreMode scoreMode = ScoreMode.Max // Defines how the scores are translated into the other side of the join.
   Query fromQuery = new TermQuery(new Term("content", searchTerm)); // Query executed to collect from values to join to the to values

   Query joinQuery = JoinUtil.createJoinQuery(fromField, multipleValuesPerDocument, toField, fromQuery, fromSearcher, scoreMode);
   TopDocs topDocs = toSearcher.search(joinQuery, 10); // Note: toSearcher can be the same as the fromSearcher
   // Render topDocs...