Elasticsearch 中不区分大小写的字段

Case insensitive fields in Elasticsearch

我将 NEST 与 ElasticSearch 结合使用,并尝试通过允许用户在搜索框中键入搜索短语来进行搜索。除了当用户输入搜索短语时他们需要确保字段名称与 Elastic 搜索中的字段名称大小写相同之外,一切正常。

例如,我的字段之一称为 bookTitle。如果他们像下面这样搜索那么它就有效

书名:"A Tale of Two Cities"

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

书名:"A Tale of Two Cities" 书名:"A Tale of Two Cities"

我用来搜索的代码如下。有没有人对我如何解决这个问题有任何想法。我希望有一个 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();
    }

非常感谢任何帮助。

Elasticsearch 无法实现您想要的方式。您可以控制映射,定义字段的名称,您是控制查询的人。

根据这个判断,您需要注意用户将在搜索字段中键入的内容,开箱即用的 Elasticsearch 不会帮助您使用小写字段名称或类似的东西。

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

我的建议是定义一套规则,也应该传达给您的用户。围绕这些行的东西:

  • 你的字段名全部小写,或者camel-cased
  • 您将映射定义为 strict,这样您就可以完全控制它
  • 您通知用户(在 Web 界面或 UI 中)他们应该根据一组规则搜索字段名称(仅限小写字母,或仅限驼峰字母等)

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

只是为了提这个但无论如何我不推荐它,我认为你可以使用script 对 Groovy 中的字段名做任何你想做的事。但是,这意味着 您将无法使用 Elasticsearch 的真正力量。

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

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

实际上 UI 可以在他们打字时即时执行此操作并帮助他们选择正确的选项。

尚未将其作为生产质量进行测试,但理论上您可以使用小写命名策略和 .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);

这会将您的字段存储为小写。然后当您查询时,只需将用户提供的所有字段强制为小写即可。

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