我的数据如下所示。
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 时。我认为这将节省空间并在构造 Document 和 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”执行布尔查询?