当前位置: 首页 > 面试题库 >

如何使用Nest C#Client在Elasticsearch中进行重音不敏感搜索?

潘修文
2023-03-14
问题内容

我是Elasticsearch新手。

可以说我们有一个这样的类:

public class A
{
    public string name;
}

我们有2个文档,其名称分别为 “Ayşe”“ Ayse”

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

例如:当我搜索 “ Ayse”“Ayşe”时 ,它应同时返回存储的 “Ayşe”和“ Ayse” (带有重音符号)。

现在,当我搜索“ Ayse”时,它仅返回“ Ayse”,但我也希望得到“Ayşe”。

当我查看Elasticsearch文档时,我发现需要使用折叠属性来实现这一点。但是我不明白如何使用Nest属性/函数。

顺便说一句,我现在正在使用自动映射来创建映射,如果可能的话,我希望能够继续使用它。

我正在寻找为期2天的答案,目前还无法解决。

需要什么/在哪里进行更改?可以给我提供代码示例吗?

谢谢。

编辑1:

我想出了如何使用分析器来创建属性的子字段并通过针对子字段的基于术语的查询来获得结果。

现在,我知道我可以进行多字段搜索,但是 有没有办法在全文搜索中包含子字段?

谢谢。


问题答案:

您可以配置分析器以在索引时对文本进行分析,将其索引到要在查询时使用的multi_field中,以及保留原始源以返回结果。根据您所遇到的问题,听起来像您想要一个自定义分析器,该分析器使用asciifolding令牌过滤器在索引和搜索时转换为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该分析器将标准令牌生成standard器与folding-preserve令牌过滤器和执行ascii
的令牌过滤器结合使用折叠,除了折叠的令牌外,还存储原始令牌(更多有关为什么可能在一分钟内有用的信息)。

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

现在让我们索引一些文档

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);

最后,搜索 Ayşe

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")
        )
    )
);

产量

{
  "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包含发送到Elasticsearch的原始文本,因此使用response.Documents,您将获得原始名称,例如

string.Join(",", response.Documents.Select(d => d.Name));

会给你“Ayşe,Ayse”

其次,还记得我们将原始令牌保留在asiifolding令牌过滤器中吗?这样做意味着我们可以执行经过分析的查询,以不敏感地匹配重音,但在计分时也要考虑重音;在上面的例子中,得分
艾谢费里德阿卡尔 匹配 艾谢费里德阿卡尔 比更高 艾谢费里德阿卡尔 匹配 艾谢费里德阿卡尔 因为令牌 艾谢费里德阿卡尔
艾谢费里德阿卡尔 被索引为前,而仅 艾谢费里德阿卡尔
被索引为后者。当针对该Name属性执行要进行分析的查询时,将使用对该查询进行分析并执行对folding-analyzer匹配项的搜索

Index time
----------

document 1 name: Ayse --analysis--> Ayse

document 2 name: Ayşe --analysis--> Ayşe, Ayse


Query time
-----------

query_string query input: Ayşe --analysis--> Ayşe, Ayse

search for documents with tokens for name field matching Ayşe or Ayse


 类似资料:
  • 问题内容: 我有一个带有utf8一般ci排序规则的MySQL表。在表中,我可以看到两个条目: 阿巴德 阿巴德 我正在使用如下查询: 查询结果给出两个词: 阿巴德 阿巴德 有没有办法表明我只希望MySQL找到带重音的单词?我希望查询仅返回 阿巴德 我也尝试过以下查询: 它没有给我任何结果。感谢您的帮助。 问题答案: 如果您对该字段的搜索始终对重音敏感,则将该字段的排序规则声明为utf8_bin(这将

  • 我正在使用Hibernate Search/Lucene Intégration开发一个J2E应用程序。我索引文档(和其他实体),并希望对其进行不区分重音的搜索(内容和类的字段)。 这样做好吗?是否没有param或conf属性让FrenchAnalyzer忽略重音? 谢谢

  • 问题内容: 所需结果: 在MySQL中具有重音敏感的主键。 我有一个独特的单词表,所以我将单词本身用作主键(顺便说一句,如果有人可以给我一些建议,我不知道它是否是一个好的设计/实践)。 我需要使该字段具有重音(为什么不区分大小写),因为它必须区分法语动词“ demander”的两个不同的变体,例如和。我在数据库中存储重音词没有任何问题。我只是无法插入没有重音时相同的两个重音字符字符串。 错误 :

  • 问题内容: 有什么方法可以使搜索查询的重音不敏感吗? 列和表的排序规则是utf8_polish_ci,我不想更改它们。 例句:toruń 它找不到“toruń”。我怎样才能做到这一点? 问题答案: 您可以在运行时在sql查询中更改排序规则, 但是请注意,在运行时即时更改排序规则会放弃mysql使用索引的可能性,因此大型表的性能可能很糟糕。 或者,您可以将列复制到另一列,例如,但是更改其排序规则。这

  • 问题内容: 我有一个MySQL数据库,其单词包含西班牙语(áéíóú)的重音。我想知道是否有任何方法可以进行变音符号不敏感搜索。例如,如果我搜索“ lapiz”(不带重音),我想从数据库中获取包含“lápiz”一词的结果。我当前执行查询的方式如下: 这是一家在线商店,所以我不知道人们会搜索什么……“ lapiz”只是一个例子。 替代文字http://www.freeimagehosting.net

  • 问题内容: 我有两个具有以下映射的索引(我将简化它们的映射): 1)AccountType映射: 2)ProductType映射: 现在,我有几件事需要弄清楚: 1)首先,有一个索引是一个好主意,在我的情况下是帐户,并且产品是嵌套对象,但是在这里每次我要更新/添加新产品时,我都必须重新索引(更新)整个帐户文件? 2)我的第二个问题是:我想具有搜索功能,因此,如果用户通过在文本框中键入内容进行搜索,