2

我正在使用 solr 字符串字段在文本字段上提供精确匹配(我查看了文本字段类型,但不相信它对我有用 - 我想准确重现 Sql 的 LIKE 功能,包括空格和通配符)。

我的问题是当我索引大文本字段时,Solr 在搜索这些字段时不会返回任何数据。限制似乎是 int16.max。

作为测试,我创建了一个包含一个id字段和一个string字段的索引。如果该id字段为“1”并且该string字段包含 40,000 个字符:

  • id:1将返回带有 40,000 个字符的两个字段,表明它确实被索引了。
  • string:*不返回任何结果

如果字符串字段仅包含 30,000 个字符,那么一切似乎都可以正常工作。

我找不到任何说明这是一个限制的文档,也找不到任何解决方法,因为 maxFieldLength 在 4.0 中被删除并且字符串字段不支持分析器。

有没有其他人遇到过这个问题或找到了解决方法?

4

1 回答 1

2

我在这方面花了很多时间,所以我发布了我想出的解决方案,以防其他人遇到这个问题。使用带有 KeywordTokenizer 的文本字段类型确实像字符串字段一样工作,一直到我在使用字符串字段类型时遇到的长度限制。

最终,我在阅读了这个线程后创建了一个自定义标记器,并进行了一些更改:

  1. 他想要标准行为,所以他基于 StandardTokenizer,而我希望它像字符串字段一样。我第一次尝试使用 KeywordTokenizer,但仍然遇到限制,所以最终我基于 WhitespaceTokenizer(更多内容见下文)。

  2. 那里的代码已过时,不适用于 Solr 4.0。

WhitespaceTokenizer 的代码很短,它包含一个称为isTokenChar返回的方法!Character.isWhitespace(c);。我只是将其更改为始终返回 true。之后,我创建了一个 TokenizerFactory 来返回它并在 schema.xml 中引用它,就像链接线程一样。

MyCustomTokenizer.java:

package custom.analysis;

import java.io.Reader;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.util.CharTokenizer;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.Version;

public final class MyCustomTokenizer extends CharTokenizer {

  public MyCustomTokenizer(Version matchVersion, Reader in) {
    super(matchVersion, in);
  }

  public MyCustomTokenizer(Version matchVersion, AttributeSource source, Reader in) {
    super(matchVersion, source, in);
  }

  public MyCustomTokenizer(Version matchVersion, AttributeFactory factory, Reader in) {
    super(matchVersion, factory, in);
  }

  @Override
  protected boolean isTokenChar(int c) {
    return true; //!Character.isWhitespace(c);
  }
}

MyCustomTokenizerFactory.java:

package custom.analysis;

import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.analysis.core.KeywordTokenizerFactory;
import org.apache.lucene.analysis.core.KeywordTokenizer;

import java.io.Reader; 
import org.apache.lucene.util.Version;


public class MyCustomTokenizerFactory extends TokenizerFactory {
  public MyCustomTokenizer create(Reader input) { 
    final MyCustomTokenizer tokenizer = new MyCustomTokenizer(Version.LUCENE_40, input); 
    return tokenizer; 
  } 
} 

架构.xml:

<fieldType name="text_block" class="solr.TextField" positionIncrementGap="100"> 
   <analyzer> 
     <tokenizer class="custom.analysis.MyCustomTokenizerFactory" />        
   </analyzer> 
</fieldType> 

使用这种方法,我能够使用字符串字段等功能索引大型文本字段(>100k 个字符)。如果有人找到更好的方法,请发布!

于 2013-03-12T17:57:31.917 回答