【问题标题】:How to migrate custom TokenFilter from Lucene.Net 3.0.3 to 4.8如何将自定义 TokenFilter 从 Lucene.Net 3.0.3 迁移到 4.8
【发布时间】:2021-07-16 17:57:10
【问题描述】:

我有以下适用于 Lucene.Net 3.0.3 的自定义 TokenFilter,我需要将其迁移到 Lucene.Net 4.8:

public sealed class AccentFoldingFilter : TokenFilter
{
    private ITermAttribute termAttribute;

    public AccentFoldingFilter(TokenStream input) : base(input)
    {
        termAttribute = this.input.GetAttribute<ITermAttribute>();
    }

    public override bool IncrementToken()
    {
        if (this.input.IncrementToken())
        {
            termAttribute.SetTermBuffer(termAttribute.Term.RemoveDiacritics());
            return true;
        }
        return false;
    }
}

ITermAttribute 不再存在,我想我需要使用ICharTermAttribute 但我不知道该怎么做。

如何在 4.8 中做同样的事情?

作为参考,这是RemoveDiacritics 扩展方法:

public static string RemoveDiacritics(this string text)
{
    var normalizedString = text.Normalize(NormalizationForm.FormD);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

【问题讨论】:

    标签: c# lucene.net


    【解决方案1】:

    尽管您可以使用下面的答案,但请注意 Lucene.NET 4.8.0 在框中包含一个 ICUNormalizer2Filter、一个 ICUNormalizer2CharFilter 和一个 ICUFoldingFilter。但是,您可能仍然倾向于使用现有的解决方案,而不是拖入 20MB+ 的依赖项 (ICU4N)。

    要翻译,您需要将ICharTermAttribute 直接添加到您的过滤器中(而不是TokenStream)。该属性将通过调用GetAttribute&lt;ICharTermAttribute&gt;() 从令牌流的共享上下文中拉出。

    public sealed class AccentFoldingFilter : TokenFilter
    {
        private ICharTermAttribute termAttribute;
    
        public AccentFoldingFilter(TokenStream input) : base(input)
        {
            termAttribute = this.GetAttribute<ICharTermAttribute>();
        }
    
        public override bool IncrementToken()
        {
            if (this.m_input.IncrementToken())
            {
                string buffer = termAttribute.ToString().RemoveDiacritics();
                termAttribute.SetEmpty().Append(buffer);
                return true;
            }
            return false;
        }
    }
    

    另外,RemoveDiacritics 方法的实现没有考虑代理对,这可能会导致以后难以诊断错误。

    public static string RemoveDiacritics(this string text)
    {
        var normalizedString = text.Normalize(NormalizationForm.FormD);
        int inputLength = normalizedString.Length;
        char[] buffer = new char[inputLength];
    
        // TODO: If the strings are short (less than 256 chars),
        // consider using this (must be unsafe context)
    
        // char* buffer = stackalloc char[inputLength];
    
        int bufferLength = 0;
    
        for (int i = 0; i < inputLength;)
        {
            // Handle surrogate pairs
            int charCount = char.IsHighSurrogate(normalizedString, i)
                && i < inputLength - 1
                && char.IsLowSurrogate(normalizedString, i + 1) ? 2 : 1;
    
            var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(normalizedString, i);
            if (unicodeCategory != UnicodeCategory.NonSpacingMark)
            {
                buffer[bufferLength++] = normalizedString[i]; // high surrogate / BMP char
                if (charCount == 2)
                {
                    buffer[bufferLength++] = normalizedString[i + 1]; // low surrogate
                }
            }
            i += charCount;
        }
    
        return new string(buffer, 0, bufferLength).Normalize(NormalizationForm.FormC);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 2022-01-16
      • 2023-03-24
      • 2017-10-01
      • 1970-01-01
      相关资源
      最近更新 更多