IRavenQueryable<T> 搜索找不到&-sign(或其他特殊字符)
IRavenQueryable<T> Search can't find &-sign (or other special characters)
在我们自己的RavenQueryableExtensions
class中我们有以下方法:
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 数组中创建一个包含所有松散搜索词的搜索查询。但是,它似乎无法识别 &
或 .
等特殊字符。例如:
- 我们有一份公司名单。其中一家公司的名称为 "A & A something more".
- 当我输入搜索 "A & A" 或仅输入“&”时,它没有找到这家公司。
- 它在我调试时生成了以下查询:
{Query:(A*) AND Query:(\&*) AND Query:(A*)}
- 当我输入任何其他特殊字符(如“.”)时也是如此。或“`”。
有谁知道如何更改搜索方法以正确设置这些特殊字符的格式?
此外,我不知道它是否与我们的问题相关,但我们也使用 AsciiFoldingAnalyzer
class(见下文)。这 class 允许我们在输入 "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);
}
}
好的,事实证明这很容易。我们在我们的分析器中使用了一个基本的 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" 和“&”的所有匹配项,所以也许我们需要更改还有一些事情可以缩小范围,但至少我在问这个问题时得到了我想要的。
在我们自己的RavenQueryableExtensions
class中我们有以下方法:
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 数组中创建一个包含所有松散搜索词的搜索查询。但是,它似乎无法识别 &
或 .
等特殊字符。例如:
- 我们有一份公司名单。其中一家公司的名称为 "A & A something more".
- 当我输入搜索 "A & A" 或仅输入“&”时,它没有找到这家公司。
- 它在我调试时生成了以下查询:
{Query:(A*) AND Query:(\&*) AND Query:(A*)}
- 当我输入任何其他特殊字符(如“.”)时也是如此。或“`”。
有谁知道如何更改搜索方法以正确设置这些特殊字符的格式?
此外,我不知道它是否与我们的问题相关,但我们也使用 AsciiFoldingAnalyzer
class(见下文)。这 class 允许我们在输入 "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);
}
}
好的,事实证明这很容易。我们在我们的分析器中使用了一个基本的 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" 和“&”的所有匹配项,所以也许我们需要更改还有一些事情可以缩小范围,但至少我在问这个问题时得到了我想要的。