【问题标题】:is it possible to search for documents with missing fields in lucene?是否可以在 lucene 中搜索缺少字段的文档?
【发布时间】:2013-08-15 18:26:16
【问题描述】:

我的数据如下所示。

X1, X2, X3
1,  1,  0
0,  0,  1

如果您注意到,有 3 列:X1、X2 和 X3。这些列中的每一列的值只有 1 或 0。希望将此数据中的每一行作为 lucene 文档进行索引,并且希望将每行的每一列作为 lucene 字段进行索引。

实际上,我拥有的列数超过 100,000。而且,这些数据非常稀疏;也就是说,绝大多数值都是零。当我尝试将每一行索引为文档时,我得到一个 OutOfMemoryError。当然,我可以修改 JVM Xms 和 Xmx 设置以及 IndexWriterConfig 来尝试解决这个内存问题。 (谁知道呢,但 lucene 中每个 Document 的字段数也可能有限制)。我的代码如下所示。

IndexWriter writer = ...
BufferedReader reader = ....
String line = null;
while(null != (line = reader.readLine()) {
 String[] tokens = line.split(",");
 Document doc = new Document();
 for(int i=0; i < tokens.length; i++) {
  doc.add(new IntField("x"+i, Integer.parseInt(tokens[i]), Field.Store.NO));
 }
 writer.addDocument(doc);
}

但是,由于数据集是稀疏的,我真正想做的是将列值索引为字段,仅当其值为 1 时。我认为这将节省空间并在构造文档和 lucene 索引。所以我想修改我的代码的 for 循环,如下所示。

 for(int i=0; i < tokens.length; i++) {
  int val = Integer.parseInt(tokens[i]);
  if(0 != val)
   doc.add(new IntField("x"+i, val, Field.Store.NO));
 }

我的问题是:如果我不将值为零的列作为每行的字段进行索引,我可以查询没有字段的文档吗?

例如,如果我天真地索引所有字段而不管值是 0 还是 1,我可以执行如下查询。

IndexReader reader = ...
IndexSearcher searcher = ...
Query q1 = NumericRangeQuery.newIntRange("x1", 1, 1, true, true);
Query q2 = NumericRangeQuery.newIntRange("x2", 0, 0, true, true);
BooleanQuery query = new BooleanQuery();
query.add(q1, Occur.MUST);
query.add(q2, Occur.MUST);
TopDocs topDocs = searcher.search(query, null, 1); 

这将为我提供 x1=1 和 x2=0 的所有文档。

如果我采用稀疏索引方法(我不索引值为 0 的字段),是否可以查询 x1=1 和 x2=0 的文档。如果是这样,有人可以给我一个例子吗?

我了解到您可以使用 elasticsearch(和 solr)进行此类查询,但我无法在我的环境中使用此类技术。另外,我确实在互联网上得到了一些调查这个问题的搜索结果,但这些帖子来自处理早期版本的 lucene(例如,一篇帖子是在 2005 年)。

请注意,我正在使用 jdk 1.7 32 位和 lucene v4.4。

感谢任何帮助。

我只是想到了一些东西,我会尝试一下。可能我可以如下索引一个字段中的每一行。

x1=0 x2=1 x3=0
x1=0 x2=0 x3=1

然后我可以对“x1=0”和“x2=1”执行布尔查询?

【问题讨论】:

    标签: solr elasticsearch lucene


    【解决方案1】:

    是的,您可以通过获取所有文档并消除具有值的文档(使用Occur.MUST_NOT)来执行这样的查询,例如:

    Query qx2 = NumericRangeQuery.newIntRange("x2", 1, 1, true, true);
    Query matchAll = new MatchAllDocsQuery();
    Query qnotx2 = new BooleanQuery();
    query.add(matchAll, Occur.MUST);
    query.add(qx2, Occur.MUST_NOT);
    Query qx1 = NumericRangeQuery.newIntRange("x1", 1, 1, true, true);
    Query query = new BooleanQuery();
    query.add(qx1, Occur.MUST);
    query.add(qnotx2, Occur.MUST);
    TopDocs topDocs = searcher.search(query, null, 1); 
    

    但是,以我能想象的任何方式,这都不太可能节省大量内存空间。就存储而言,不存储字段,索引中的公共值应该占用微不足道的空间。使用这种方法,查询时的性能会更差,而索引零会更好。

    【讨论】:

    • 你知道lucene v4.4中每个文档的字段数有上限吗?
    • 在一个字段中索引所有内容是否有效?例如索引文本,“x1=0 x2=0 x3=1”?然后是否可以查询字段具有“x1=0 和 x2=0”的任何文档?
    • 我不认为文档中的字段数量存在内置限制。据我所知,硬件限制应该是唯一的限制。
    • 是的,您当然可以索引一个字段中的所有内容。这可能是一个很好的尝试,但您需要仔细选择您的分析器。 WhitespaceAnalyzer 可能是一个不错的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    相关资源
    最近更新 更多