【问题标题】:How can I solve turkish letter issue in elasticsearch by using C# nest?如何使用 C# Nest 解决 Elasticsearch 中的土耳其字母问题?
【发布时间】:2017-03-23 11:02:18
【问题描述】:

在土耳其,我们有土耳其语字母,例如“ğ”、“ü”、“ş”、“ı”、“ö”、“ç”。但是当我们一般搜索时,我们使用字母“g”、“u”、“s”、“i”、“o”、“c”。这不是一个规则,但我们通常会这样做,像一种习惯一样思考,我们曾经这样做过。例如,如果我写驼峰式“Ş”,则应搜索“ş”和“s”。请看这个链接,它是一样的。但是他们的解决方案太长而且不完美。我怎么能在下面?

我的目标是这样的:

ProductName 或 Category.CategoryName 可能包含土耳其语字母(“Eşarp”),或者有些可能输入错误并用英文字母书写(“Esarp”) 查询字符串可能包含土耳其语字母(“eşarp”)或不包含(“esarp”) 查询字符串可能有多个单词 应根据查询字符串搜索每个索引字符串字段(全文搜索)

indexing and full text searching in elasticsearch without dialitics using c# client Nest

我的代码是:


  try
            {
                var node = new Uri(ConfigurationManager.AppSettings["elasticseachhost"]);
                var settings = new ConnectionSettings(node);
                settings.DefaultIndex("defaultindex").MapDefaultTypeIndices(m => m.Add(typeof(Customer), "myindex"));
                var client = new ElasticClient(settings);



                string command = Resource1.GetAllData;
                using (var ctx = new SearchEntities())
                {
                    Console.WriteLine("ORacle db is connected...");
                    var customers = ctx.Database.SqlQuery(command).ToList();
                    Console.WriteLine("Customer count : {0}", customers.Count);
                    if (customers.Count > 0)
                    {
                        var delete = client.DeleteIndex(new DeleteIndexRequest("myindex"));
                        foreach (var customer in customers)
                        {

                            client.Index(customer, idx => idx.Index("myindex"));
                            Console.WriteLine("Data is indexed in elasticSearch engine");
                        }


                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
                Console.WriteLine(ex.Message);
            }

我的实体:


 public class Customer
    {
        public string Name{ get; set; }
        public string SurName { get; set; }
        public string Address{ get; set; }
}

我想我想要的解决方案是:(Create index with multi field mapping syntax with NEST 2.x)

但我无法理解。


Check this out:

[Nest.ElasticsearchType]
public class MyType
{
    // Index this & allow for retrieval.
    [Nest.Number(Store=true)]
    int Id { get; set; }

    // Index this & allow for retrieval.
    // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens.
    [Nest.String(Store = true, Index=Nest.FieldIndexOption.Analyzed, TermVector=Nest.TermVectorOption.WithPositionsOffsets)]
    string CompanyName { get; set; }

    // Don't index this for searching, but do store for display.
    [Nest.Date(Store=true, Index=Nest.NonStringIndexOption.No)]
    DateTime CreatedDate { get; set; }

    // Index this for searching BUT NOT for retrieval/displaying.
    [Nest.String(Store=false, Index=Nest.FieldIndexOption.Analyzed)]
    string CompanyDescription { get; set; }

    [Nest.Nested(Store=true, IncludeInAll=true)]
    // Nest this.
    List Locations { get; set; }
}

[Nest.ElasticsearchType]
public class MyChildType
{
    // Index this & allow for retrieval.
    [Nest.String(Store=true, Index = Nest.FieldIndexOption.Analyzed)]
    string LocationName { get; set; }

    // etc. other properties.
}
After this declaration, to create this mapping in elasticsearch you need to make a call similar to:

var mappingResponse = elasticClient.Map(m => m.AutoMap());

我对上述挑战的第二次尝试: 错误:未检测到分析。大问题是版本差异。我发现很多样本都产生了如下错误: “CreateeIndexDescriptor”不包含“分析”的定义...


using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ElasticSearchTest2
{
    class Program
    {
        public static Uri EsNode;
        public static ConnectionSettings EsConfig;
        public static ElasticClient client;
        static void Main(string[] args)
        {
            EsNode = new Uri("http://localhost:9200/");
            EsConfig = new ConnectionSettings(EsNode);
            client = new ElasticClient(EsConfig);

            var partialName = new CustomAnalyzer
            {
                Filter = new List { "lowercase", "name_ngrams", "standard", "asciifolding" },
                Tokenizer = "standard"
            };

            var fullName = new CustomAnalyzer
            {
                Filter = new List { "standard", "lowercase", "asciifolding" },
                Tokenizer = "standard"
            };

            client.CreateIndex("employeeindex5", c => c
                            .Analysis(descriptor => descriptor
                                .TokenFilters(bases => bases.Add("name_ngrams", new EdgeNGramTokenFilter
                                {
                                    MaxGram = 20,
                                    MinGram = 2,
                                    Side = "front"
                                }))
                                .Analyzers(bases => bases
                                    .Add("partial_name", partialName)
                                    .Add("full_name", fullName))
                            )
                            .AddMapping(m => m
                                .Properties(o => o
                                    .String(i => i
                                        .Name(x => x.Name)
                                        .IndexAnalyzer("partial_name")
                                        .SearchAnalyzer("full_name")
                                    ))));

            Employee emp = new Employee() { Name = "yılmaz", SurName = "eşarp" };
            client.Index(emp, idx => idx.Index("employeeindex5"));
            Employee emp2 = new Employee() { Name = "ayşe", SurName = "eşarp" };
            client.Index(emp2, idx => idx.Index("employeeindex5"));
            Employee emp3 = new Employee() { Name = "ömer", SurName = "eşarp" };
            client.Index(emp3, idx => idx.Index("employeeindex5"));
            Employee emp4 = new Employee() { Name = "gazı", SurName = "emir" };
            client.Index(emp4, idx => idx.Index("employeeindex5"));
        }
    }

    public class Employee
    {

        public string Name { set; get; }
        public string SurName { set; get; }


    }
}


【问题讨论】:

    标签: c# elasticsearch nest full-text-indexing


    【解决方案1】:

    你想要的是使用ASCII Folding Token Filter,这是从官方elasticsearch页面引用的:

    一种 asciifolding 类型的标记过滤器,将不在前 127 个 ASCII 字符(“基本拉丁语”Unicode 块)中的字母、数字和符号 Unicode 字符(如果存在)转换为它们的 ASCII 等效字符。

    这意味着它可以将ç 之类的字符转换为普通的拉丁字符(在本例中为字母c),因为它是与标准ascii 字符最接近的匹配。

    所以你可以有一个像çar 这样的值,当你想要执行搜索时,使用相同的标记过滤器搜索carçar 将返回你期望的结果。

    例如,您可以尝试以下调用:

    • 对您的 elasticsearch 实例执行此 POST 请求

    网址:

    http://YOUR_ELASTIC_SEARCH_INSTANCE_URL/_analyze/

    请求正文: { "tokenizer": "standard", "filter": [ "lowercase", "asciifolding" ], "text": "déja öne ğuess" }

    结果如下:

    {
    "tokens": [
    {
    "token": "deja",
    "start_offset": 0,
    "end_offset": 4,
    "type": "<ALPHANUM>",
    "position": 0
    }
    ,
    {
    "token": "one",
    "start_offset": 5,
    "end_offset": 8,
    "type": "<ALPHANUM>",
    "position": 1
    }
    ,
    {
    "token": "guess",
    "start_offset": 9,
    "end_offset": 14,
    "type": "<ALPHANUM>",
    "position": 2
    }
    ]
    }
    

    注意token 属性(elastic 将实际索引和处理的文本)是所提供原始文本的英文版本。

    要了解有关ASCII Folding Token Filter 的更多信息,请参阅此链接: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-asciifolding-tokenfilter.html

    注意:为了利用此技术,您需要创建自己的分析器。

    这是从自定义分析器的官方页面引用的:

    当内置分析器不能满足您的需求时,您可以创建一个自定义分析器,它使用以下适当组合:

    • 零个或多个字符过滤器

    • 分词器

    • 零个或多个令牌过滤器。

    更多关于创建自定义分析器的信息可以在这里找到:https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer-anatomy.html

    您还可以从以下答案中找到有关如何使用 NEST 创建自定义分析器的示例:Create custom token filter with NEST

    【讨论】:

    • 我们正在更新文档以包含有关 NEST 分析器的部分:)
    • 嗨;谢谢你的帮助。但问题是我如何通过 NEST 和 C# 使用它
    • @programmerist:是的,我知道您在询问 NEST,但我试图澄清解决方案背后的方式,语法不应该那么难。 :)
    • 您可以从以下问题中找到如何使用 NEST 创建自定义分析器的示例:stackoverflow.com/questions/19845020/… 我还将更新答案以包含此链接。 :)
    • @MohammedElSayed;问题是 Nest 库中的版本差异。错误:“CreateIndexDescriptor”不包含“分析”的定义...(我更新了我的问题)
    【解决方案2】:

    简单的解决方案是使用称为 Unicode 分解的东西。字符 Ş 可以拆分为 ASCII S,后跟一个组合变音符号。搜索时,您将采取以下步骤:

    • 分解字符串
    • 去掉所有的变音符号
    • 将所有剩余字符转换为小写。
    • 与类似转换的搜索键进行比较。

    具体来说,您需要FormD 分解,并通过查看它们的UnicodeCategory 来删除组合变音符号。您还可以使用该 UnicodeCategory 来删除空格和其他标点符号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-20
      • 2013-11-04
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多