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, ...)
  • 最后再次反转标记(78678567845678345678、...)。

如您所见,结果是字符串被标记化 "from the back",因此搜索 5678 将匹配 abc12345678.