Home Articles

Elasticsearch中的不区分大小写的字段

Asked
Viewed 483 times
6

我正在使用NEST和ElasticSearch,我尝试通过允许用户在搜索框中键入搜索短语来进行搜索 . 除了用户输入他们需要的搜索短语以确保字段名称与弹性搜索中的字段名称相同的情况之外,一切正常 .

例如,我的一个字段叫做bookTitle . 如果他们搜索如下,那么它的工作原理

bookTitle:“双城记”

如果他们像下面的例子一样搜索它不起作用

书签:“双城记”书名:“双城记”

我用来搜索的代码如下 . 有没有人对如何解决这个问题有任何想法 . 我希望有一个ElasticSearch / NEST设置允许我这样做,而不是用搜索文本做一些丑陋的事情,比如查找“BookTitle”并替换为“bookTitle” .

public List<ElasticSearchRecord> Search(string searchterm) {

        var results = _client.Search<ElasticSearchRecord>(s => s
                        .Query(q => q
                            .QueryString(qs => qs
                                .DefaultField("content")
                                .Query(searchterm)
                            )
                        ));


        return results.Documents.ToList();
    }

任何帮助非常感谢 .

3 Answers

  • 3

    Elasticsearch无法实现您希望的方式 . 您可以控制映射,定义字段的名称,您就是控制查询的人 .

    通过这种判断,您需要注意用户将在搜索字段中输入的内容,Elasticsearch开箱即用将无法帮助您使用小写字段名称或类似的东西 .

    因此,无论您选择哪种解决方案,都将是一种解决方法 .

    我的建议是 define a set of rules ,也应该传达给您的用户 . 围绕这些线的东西:

    • 您的字段名称都是小写的,或camel-cased

    • 您将映射定义为 strict ,以便您完全控制它

    • 您通知用户(在Web界面或UI中)他们应该在给定一组规则的情况下搜索字段名称(仅限小写,或仅限驼峰等)

    另一种方法是定义what goes into the _all field . 在 QueryString 中,您不使用特定的字段名称,ES将使用 query_string 的默认设置 . 这意味着ES将使用 _all ,一个 _all 字段,你知道它包含什么 .

    只是为了提及这个,我认为你可以使用 script 用Groovy中的字段名做任何你想做的事 . 但是,这意味着 you will not use the real power of Elasticsearch .

    如上所述,教育您的用户并定义一组要遵守的规则 .

  • 1

    您可以在C#内存中缓存映射,并确认从中找到所有搜索字段 . 如果未找到完全匹配,则尝试找到最佳匹配字段 . 如果有多个选项可供选择,则抛出错误并要求用户更具体 .

    实际上,UI可以在键入时动态执行此操作,并帮助他们选择正确的选项 .

  • 0

    尚未将其作为 生产环境 质量进行测试,但从理论上讲,您可以使用小写命名策略保存所有对象,并使用.ToLower()查询字段,以便它们始终匹配 .

    首先创建适当的命名策略:

    public class LowercaseNamingStrategy : Newtonsoft.Json.Serialization.NamingStrategy
    {
        protected override string ResolvePropertyName(string name)
        {
            return name.ToLower();
        }
    }
    

    和适当的序列化器:

    public class ElasticSerializer : JsonNetSerializer
        {
            public ElasticSerializer(IConnectionSettingsValues settings)
                : base(settings)
            {
                this.ContractResolver.NamingStrategy = new LowercaseNamingStrategy();
            }
        }
    

    然后在NEST客户端的连接设置中使用序列化程序:

    var pool = new StaticConnectionPool([your nodes]);
            var settings = new ConnectionSettings(pool, s => new ElasticSerializer(s));
            var client = new ElasticClient(settings);
    

    这会将您的字段存储为小写 . 然后在查询时,只需强制所有用户提供的字段为小写,并且事物应该排成一行 .

    如果您不是从头开始,则必须重新填充数据以保持命名策略的统一 .

Related