Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从Lucene中的特定字段获取唯一术语列表?_Java_Lucene - Fatal编程技术网

Java 如何从Lucene中的特定字段获取唯一术语列表?

Java 如何从Lucene中的特定字段获取唯一术语列表?,java,lucene,Java,Lucene,我有一个包含多个字段的大型语料库索引。这些字段中只有一个包含文本。 我需要根据这个字段从整个索引中提取唯一的单词。 有人知道我如何用java中的Lucene做到这一点吗?您正在寻找的(字段中的所有单词的集合以及每个单词的使用次数,不包括停止词)。您将为索引中的每个文档使用IndexReader,并用它们填充哈希集 另一种选择是只为您感兴趣的领域使用和选择术语: IndexReader reader = IndexReader.open(index); TermEnum terms = reade

我有一个包含多个字段的大型语料库索引。这些字段中只有一个包含文本。 我需要根据这个字段从整个索引中提取唯一的单词。 有人知道我如何用java中的Lucene做到这一点吗?

您正在寻找的(字段中的所有单词的集合以及每个单词的使用次数,不包括停止词)。您将为索引中的每个文档使用IndexReader,并用它们填充
哈希集

另一种选择是只为您感兴趣的领域使用和选择术语:

IndexReader reader = IndexReader.open(index);
TermEnum terms = reader.terms();
Set<String> uniqueTerms = new HashSet<String>();
while (terms.next()) {
        final Term term = terms.term();
        if (term.field().equals("field_name")) {
                uniqueTerms.add(term.text());
        }
}
IndexReader=IndexReader.open(index);
TermEnum terms=reader.terms();
Set uniqueTerms=new HashSet();
while(terms.next()){
最终期限=期限。期限();
if(term.field().equals(“field_name”)){
uniqueTerms.add(term.text());
}
}

这不是最佳解决方案,您正在读取,然后丢弃所有其他字段。Lucene 4中有一个类
Fields
,它只返回单个字段

如果您使用的是Lucene 4.0 api,则需要从索引读取器中获取字段。然后,字段提供了获取索引中每个字段的术语的方法。以下是如何做到这一点的示例:

        Fields fields = MultiFields.getFields(indexReader);
        Terms terms = fields.terms("field");
        TermsEnum iterator = terms.iterator(null);
        BytesRef byteRef = null;
        while((byteRef = iterator.next()) != null) {
            String term = new String(byteRef.bytes, byteRef.offset, byteRef.length);

        }
最终,对于Lucene的新版本,您可以从BytesRef调用中获取字符串:

       byteRef.utf8ToString();
而不是

       new String(byteRef.bytes, byteRef.offset, byteRef.length);
如果要获取文档频率,可以执行以下操作:

       int docFreq = iterator.docFreq();

同样的结果是,使用
lucenesuggest
包中的
LuceneDictionary
。它通过返回
BytesRefierator.EMPTY
来处理不包含任何术语的字段。这将为您节省NPE:)


使用
TermsEnum
terms.next()
的答案会因一个bug而变得微妙。这是因为
TermsEnum
已经指向第一个术语,因此
while(terms.next())
将导致跳过第一个术语

而是使用for循环:

TermEnum terms = reader.terms();
for(Term term = terms.term(); term != null; terms.next(), term = terms.term()) {
    // do something with the term
}
要根据接受的答案修改代码,请执行以下操作:

IndexReader reader = IndexReader.open(index);
TermEnum terms = reader.terms();
Set<String> uniqueTerms = new HashSet<String>();
for(Term term = terms.term(); term != null; terms.next(), term = terms.term()) {
        if (term.field().equals("field_name")) {
                uniqueTerms.add(term.text());
        }
}
IndexReader=IndexReader.open(index);
TermEnum terms=reader.terms();
Set uniqueTerms=new HashSet();
for(Term=terms.Term();Term!=null;terms.next(),Term=terms.Term()){
if(term.field().equals(“field_name”)){
uniqueTerms.add(term.text());
}
}

从Lucene 7+开始,上述链接和一些相关链接已过时

以下是当前的情况:

// IndexReader has leaves, you'll iterate through those
int leavesCount = reader.leaves().size();
final String fieldName = "content";

for(int l = 0; l < leavesCount; l++) {
  System.out.println("l: " + l);
  // specify the field here ----------------------------->
  TermsEnum terms = reader.leaves().get(l).reader().terms(fieldName).iterator();
  // this stops at 20 just to sample the head
  for(int i = 0; i < 20; i++) {
    // and to get it out, here -->
    final Term content = new Term(fieldName, BytesRef.deepCopyOf(terms.next()));
    System.out.println("i: " + i + ", term: " + content);
  }
}
//IndexReader有叶子,您将遍历这些叶子
int leaveScont=reader.leaves().size();
最终字符串fieldName=“content”;
对于(int l=0;l
TermsEnum terms=reader.leaves().get(l.reader().terms(fieldName.iterator();
//此操作在20处停止,只是为了对头部进行采样
对于(int i=0;i<20;i++){
//要把它弄出来,这里-->
最终术语内容=新术语(字段名,BytesRef.deepCopyOf(terms.next());
System.out.println(“i:+i+”,术语:+content);
}
}

我知道这个功能。但我需要整个语料库中的独特词汇。不是每个文档。是的,谢谢。我正在使用terms(),但它会将索引中的所有内容返回给我。我找不到一个地方告诉它只为一个特定的领域挑选术语。你对此有任何参考吗?如果(term.field().equals(“field_name”){…}用于你想要的字段:),即使是在Lucene 3上,你也不必扫描所有字段的术语。这似乎是未记录的,但
阅读器。术语(新术语(fieldName,termText))
将返回按字段名排序的
术语,以及按术语文本排序的同一字段中的术语。因此,如果您在上面使用
terms.term(fieldName,”)
,并且在第一次使用
时使用
break
!term.field().equals(fieldName)
,您得到的正是您想要的。但既然这是无文件记录的,它不会有一天被打破吗?就我所见,Lucene自己的
WildcardQuery
也建立在这个基础上,而且Lucene 3不太可能会有太大的变化。@milan您为什么将变量
术语
声明为
final
?有什么性能原因吗?这是现代版Lucene的正确答案。
// IndexReader has leaves, you'll iterate through those
int leavesCount = reader.leaves().size();
final String fieldName = "content";

for(int l = 0; l < leavesCount; l++) {
  System.out.println("l: " + l);
  // specify the field here ----------------------------->
  TermsEnum terms = reader.leaves().get(l).reader().terms(fieldName).iterator();
  // this stops at 20 just to sample the head
  for(int i = 0; i < 20; i++) {
    // and to get it out, here -->
    final Term content = new Term(fieldName, BytesRef.deepCopyOf(terms.next()));
    System.out.println("i: " + i + ", term: " + content);
  }
}