【问题标题】:IRavenQueryable<T> Search can't find &-sign (or other special characters)IRavenQueryable<T> 搜索找不到 &-sign(或其他特殊字符)
【发布时间】:2015-02-05 08:03:17
【问题描述】:

在我们自己的RavenQueryableExtensions 类中,我们有以下方法:

public static IRavenQueryable<T> SearchMultiple<T>(this IRavenQueryable<T> self,
    Expression<Func<T, object>> fieldSelector, string queries,
    decimal boost = 1, SearchOptions options = SearchOptions.Or)
{
    if (String.IsNullOrEmpty(queries)) throw new ArgumentNullException("queries");

    // More than two spaces or tabs are replaced with a single space
    var newQueries = Regex.Replace(queries, @"\s{2,}", " ");
    // not important for this question:
    //newQueries = SyncShared.ReplacePostcode(newQueries);
    // Splits the search-string into separate search-terms
    var searchValues = newQueries.Split(' ');

    return self.SearchMultiple(fieldSelector, searchValues, boost, options);
}

public static IRavenQueryable<T> SearchMultiple<T>(this IRavenQueryable<T> self,
    Expression<Func<T, object>> fieldSelector, IEnumerable<string> queries,
    decimal boost = 1, SearchOptions options = SearchOptions.Or)
{
    if (queries == null) throw new ArgumentNullException("queries");

    return queries.Aggregate(self, (current, query) => current.Search(fieldSelector, query + "* ", boost, options, EscapeQueryOptions.AllowPostfixWildcard));
}

这会在 searchValues-array 中创建一个包含所有松散搜索词的搜索查询。但是,它似乎无法识别像 &amp;. 这样的特殊字符。例如:

  • 我们有一份公司名单。其中一家公司的名称为“A & A something more”。
  • 当我输入搜索“A & A”或仅输入“&”时,找不到这家公司。
  • 当我调试时它生成了以下查询:{Query:(A*) AND Query:(\&amp;*) AND Query:(A*)}
  • 当我输入任何其他特殊字符(如“.”)时也是如此。或“`”。

有谁知道如何更改搜索方法,以便正确格式化这些特殊字符?

另外,我不知道它是否与我们的问题相关,但我们也使用 AsciiFoldingAnalyzer 类(见下文)。当我们输入“e”或“u”时,该类还允许我们搜索带有“é”或“ü”等字符的公司。

using System.Collections.Generic;
using System.IO;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Util;

namespace NatWa.MidOffice.RavenDb.ServerGoodies
{
    public class AsciiFoldingAnalyser : StandardAnalyzer
    {
        public AsciiFoldingAnalyser(Version matchVersion)
            : base(matchVersion)
        {
        }

        public AsciiFoldingAnalyser(Version matchVersion, ISet<string> stopWords)
            : base(matchVersion, stopWords)
        {
        }

        public AsciiFoldingAnalyser(Version matchVersion, FileInfo stopwords)
            : base(matchVersion, stopwords)
        {
        }

        public AsciiFoldingAnalyser(Version matchVersion, TextReader stopwords)
            : base(matchVersion, stopwords)
        {
        }

        public override TokenStream TokenStream(string fieldName, TextReader reader)
        {
            return new LowerCaseFilter(new ASCIIFoldingFilter(base.TokenStream(fieldName, reader)));
        }
    }
}

我们在映射中使用它,如下所示:

public class UserLijst : AbstractIndexCreationTask<UserState, UserLijstResult>
{
    public UserLijst()
    {
        Map = states => from state in states
                        select new UserLijstResult
                        {
                            Id = (UserId)state.AggregateId,
                            Naam = state.Naam,
                            Query = new object[]
                            {
                                state.Naam
                            }
                        };

        Reduce = results => from result in results
                            group result by new { result.Id } into g
                            select new UserLijstResult
                            {
                                Id = g.Key.Id,
                                Naam = g.First().Naam,
                                Query = g.First().Query
                            };

        Index("Query", FieldIndexing.Analyzed);
        Analyze(result => result.Query, typeof(AsciiFoldingAnalyser).AssemblyQualifiedName);
    }
}

【问题讨论】:

    标签: c# search escaping ravendb iqueryable


    【解决方案1】:

    好的,事实证明这很容易。我们在分析器中使用了一个基本的 Tokenizer,它过滤掉所有特殊字符和长度为 1 的字符。当我们替换时

    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {
        return new LowerCaseFilter(new ASCIIFoldingFilter(base.TokenStream(fieldName, reader)));
    }
    

    在我们的 AsciiFoldingAnalyser 中用于:

    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {
        return new LowerCaseFilter(new ASCIIFoldingFilter(new WhitespaceTokenizer(reader)));
    }
    

    它有效。我们可以搜索特殊字符。

    我们现在得到了很多结果,比如“A & A”这样的搜索,因为它会在所有索引字段中找到所有出现的字符“a”和“&”,所以也许我们需要更改更多内容缩小范围,但至少我在问这个问题时得到了我想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 2023-03-18
      • 2015-06-07
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多