如何使用nest c#client在elasticsearch中进行重音不敏感搜索?

时间:2016-05-26 11:15:39

标签: c# elasticsearch nest

我是一名有弹性的新手。

假设我们有这样一个类:

public class A
{
    public string name;
}

我们有2个文件,其名称类似于“Ayşe”“Ayse”

现在,我希望能够存储带有重音符号的名称,但是当我搜索时希望能够将重音不敏感查询的结果作为重音敏感结果

例如:当我搜索“Ayse”“Ayşe”时,它应该返回“Ayşe”和“Ayse”因为他们存储(带重音)。

现在当我搜索“Ayse”时,它只会返回“Ayse”,但我也想要“Ayşe”。

当我检查elasticsearch文档时,我发现需要使用折叠属性来实现它。但我无法理解如何使用Nest属性/函数。

BTW我正在使用AutoMap立即创建映射,如果可能的话,我希望能够继续使用它。

我现在正在寻找2天的答案,但还是想不通。

需要进行哪些/哪些更改?你能给我提供代码样本吗?

谢谢。

编辑1:

我想出了如何使用分析器来创建属性的子字段,并使用基于术语的子字段查询来实现结果。

现在,我知道我可以进行多字段搜索,但是是否可以使用全文搜索来包含子字段?

谢谢。

1 个答案:

答案 0 :(得分:2)

您可以在索引时对文本configure an analyzer to perform analysis进行索引,将其编入multi_field以在查询时使用,并保留原始来源以在结果中返回。根据您在问题中的含义,您可能希望自定义分析器使用asciifolding token filter在索引和搜索时转换为ASCII字符。

鉴于以下文件

public class Document
{
    public int Id { get; set;}
    public string Name { get; set; }
}

创建索引时可以设置自定义分析器;我们也可以同时指定映射

client.CreateIndex(documentsIndex, ci => ci
    .Settings(s => s
        .NumberOfShards(1)
        .NumberOfReplicas(0)
        .Analysis(analysis => analysis
            .TokenFilters(tokenfilters => tokenfilters
                .AsciiFolding("folding-preserve", ft => ft
                    .PreserveOriginal()
                )
            )
            .Analyzers(analyzers => analyzers
                .Custom("folding-analyzer", c => c
                    .Tokenizer("standard")
                    .Filters("standard", "folding-preserve")
                )
            )
        )
    )
    .Mappings(m => m
        .Map<Document>(mm => mm
            .AutoMap()
            .Properties(p => p
                .String(s => s
                    .Name(n => n.Name)
                    .Fields(f => f
                        .String(ss => ss
                            .Name("folding")
                            .Analyzer("folding-analyzer")
                        )
                    )
                    .NotAnalyzed()
                )
            )
        )
    )
);

这里我创建了一个带有一个分片而没有副本的索引(您可能希望为您的环境更改此代码),并创建了一个自定义分析器folding-analyzer,它将标准分词器与{一起使用{1}}令牌过滤器和执行ascii折叠的standard令牌过滤器,除了折叠的令牌之外还存储原始令牌(更多关于为什么这可能在一分钟内有用)。

我还映射了folding-preserve类型,将Document属性映射为Name,默认字段multi_field(对聚合很有用)和{{1将使用not_analyzed分析的子字段。默认情况下,原始源文档也将由Elasticsearch存储。

现在让我们索引一些文件

.folding

最后,搜索Ayşe

folding-analyzer

产量

client.Index<Document>(new Document { Id = 1, Name = "Ayse" });
client.Index<Document>(new Document { Id = 2, Name = "Ayşe" });

// refresh the index after indexing to ensure the documents just indexed are
// available to be searched
client.Refresh(documentsIndex);

这里要强调两件事:

首先,var response = client.Search<Document>(s => s .Query(q => q .QueryString(qs => qs .Fields(f => f .Field(c => c.Name.Suffix("folding")) ) .Query("Ayşe") ) ) ); 包含发送到Elasticsearch的原始文本,因此使用{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.163388, "hits" : [ { "_index" : "documents", "_type" : "document", "_id" : "2", "_score" : 1.163388, "_source" : { "id" : 2, "name" : "Ayşe" } }, { "_index" : "documents", "_type" : "document", "_id" : "1", "_score" : 0.3038296, "_source" : { "id" : 1, "name" : "Ayse" } } ] } } ,您将获得原始名称,例如

_source

会给你“Ayşe,Ayse”

其次,请记住我们在asciifolding令牌过滤器中保留了原始令牌吗?这样做意味着我们可以执行经过分析的查询以不敏感地匹配重音,但在评分时也会考虑重音敏感度;在上面的示例中,匹配AyşeAyşe的分数高于 Ayse 匹配Ayşe的分数,因为代币< em>Ayşe和 Ayse 为前者编制索引,而 Ayse 仅为后者编入索引。当针对response.Documents属性执行经历分析的查询时,将使用string.Join(",", response.Documents.Select(d => d.Name)); 分析查询并执行匹配搜索

Name