Nest Elasticsearch- 搜索一些字段的前面和其他字段的后面
Nest Elasticsearch- searching front of some fields and back of others
我有一个案例,我需要对某些属性(姓氏和名字)的第一部分进行部分匹配,并在其他一些属性的末尾进行部分匹配,我想知道如何添加两者分析仪。
例如,如果我的名字是 "elastic",我现在可以搜索 "elas" 并找到它。但是,如果我的帐号是 abc12345678,我需要搜索“5678”并找到所有以该结尾的帐号,但我无法通过名字搜索 "stic" 找到 "elastic" .
这是我的人物的简化示例 class:
public class Person
{
public string AccountNumber { get; set; }
[ElasticProperty(IndexAnalyzer = "partial_name", SearchAnalyzer = "full_name")]
public string LastName { get; set; }
[ElasticProperty(IndexAnalyzer = "partial_name", SearchAnalyzer = "full_name")]
public string FirstName { get; set; }
}
这是我创建索引的相关现有代码,目前非常适合搜索单词的开头:
//Set up analyzers on some fields to allow partial, case-insensitive searches.
var partialName = new CustomAnalyzer
{
Filter = new List<string> { "lowercase", "name_ngrams", "standard", "asciifolding" },
Tokenizer = "standard"
};
var fullName = new CustomAnalyzer
{
Filter = new List<string> { "standard", "lowercase", "asciifolding" },
Tokenizer = "standard"
};
var result = client.CreateIndex("persons", c => c
.Analysis(descriptor => descriptor
.TokenFilters(bases => bases.Add("name_ngrams", new EdgeNGramTokenFilter
{
MaxGram = 15, //Allow partial match up to 15 characters.
MinGram = 2, //Allow no smaller than 2 characters match
Side = "front"
}))
.Analyzers(bases => bases
.Add("partial_name", partialName)
.Add("full_name", fullName))
)
.AddMapping<Person>((m => m.MapFromAttributes()))
);
我似乎可以添加另一个 EdgeNGramTokenFilter,并使 Side = "back",但我不希望名字和姓氏搜索匹配背面搜索。有人可以提供一种方法吗?
谢谢,
阿德里安
编辑
为了完整起见,这是 属性 上的新装饰器,它与接受的答案中的代码一起使用:
[ElasticProperty(IndexAnalyzer = "partial_back", SearchAnalyzer = "full_name")]
public string AccountNumber { get; set; }
您需要声明另一个分析器(让我们称之为 partialBack
)专门用于从后面进行匹配,但您绝对可以重用现有的 edgeNGram
标记过滤器,如下所示:
var partialBack = new CustomAnalyzer
{
Filter = new List<string> { "lowercase", "reverse", "name_ngrams", "reverse" },
Tokenizer = "keyword"
};
...
.Analyzers(bases => bases
.Add("partial_name", partialName)
.Add("partial_back", partialBack))
.Add("full_name", fullName))
)
这里的关键是 reverse
标记过滤器的双重使用。
字符串 (abc12345678
) 是
- 首先小写 (
abc12345678
),
- 然后反转 (
87654321cba
),
- 然后边 ngramed (
87
, 876
, 8765
, 87654
, 876543
, ...)
- 最后再次反转标记(
78
、678
、5678
、45678
、345678
、...)。
如您所见,结果是字符串被标记化 "from the back",因此搜索 5678
将匹配 abc12345678
.
我有一个案例,我需要对某些属性(姓氏和名字)的第一部分进行部分匹配,并在其他一些属性的末尾进行部分匹配,我想知道如何添加两者分析仪。 例如,如果我的名字是 "elastic",我现在可以搜索 "elas" 并找到它。但是,如果我的帐号是 abc12345678,我需要搜索“5678”并找到所有以该结尾的帐号,但我无法通过名字搜索 "stic" 找到 "elastic" .
这是我的人物的简化示例 class:
public class Person
{
public string AccountNumber { get; set; }
[ElasticProperty(IndexAnalyzer = "partial_name", SearchAnalyzer = "full_name")]
public string LastName { get; set; }
[ElasticProperty(IndexAnalyzer = "partial_name", SearchAnalyzer = "full_name")]
public string FirstName { get; set; }
}
这是我创建索引的相关现有代码,目前非常适合搜索单词的开头:
//Set up analyzers on some fields to allow partial, case-insensitive searches.
var partialName = new CustomAnalyzer
{
Filter = new List<string> { "lowercase", "name_ngrams", "standard", "asciifolding" },
Tokenizer = "standard"
};
var fullName = new CustomAnalyzer
{
Filter = new List<string> { "standard", "lowercase", "asciifolding" },
Tokenizer = "standard"
};
var result = client.CreateIndex("persons", c => c
.Analysis(descriptor => descriptor
.TokenFilters(bases => bases.Add("name_ngrams", new EdgeNGramTokenFilter
{
MaxGram = 15, //Allow partial match up to 15 characters.
MinGram = 2, //Allow no smaller than 2 characters match
Side = "front"
}))
.Analyzers(bases => bases
.Add("partial_name", partialName)
.Add("full_name", fullName))
)
.AddMapping<Person>((m => m.MapFromAttributes()))
);
我似乎可以添加另一个 EdgeNGramTokenFilter,并使 Side = "back",但我不希望名字和姓氏搜索匹配背面搜索。有人可以提供一种方法吗? 谢谢, 阿德里安
编辑
为了完整起见,这是 属性 上的新装饰器,它与接受的答案中的代码一起使用:
[ElasticProperty(IndexAnalyzer = "partial_back", SearchAnalyzer = "full_name")]
public string AccountNumber { get; set; }
您需要声明另一个分析器(让我们称之为 partialBack
)专门用于从后面进行匹配,但您绝对可以重用现有的 edgeNGram
标记过滤器,如下所示:
var partialBack = new CustomAnalyzer
{
Filter = new List<string> { "lowercase", "reverse", "name_ngrams", "reverse" },
Tokenizer = "keyword"
};
...
.Analyzers(bases => bases
.Add("partial_name", partialName)
.Add("partial_back", partialBack))
.Add("full_name", fullName))
)
这里的关键是 reverse
标记过滤器的双重使用。
字符串 (abc12345678
) 是
- 首先小写 (
abc12345678
), - 然后反转 (
87654321cba
), - 然后边 ngramed (
87
,876
,8765
,87654
,876543
, ...) - 最后再次反转标记(
78
、678
、5678
、45678
、345678
、...)。
如您所见,结果是字符串被标记化 "from the back",因此搜索 5678
将匹配 abc12345678
.