【问题标题】:Case insensitive fields in ElasticsearchElasticsearch 中不区分大小写的字段
【发布时间】:2023-03-23 10:07:01
【问题描述】:

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

例如,我的一个字段名为 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();
    }

非常感谢任何帮助。

【问题讨论】:

  • 因此,如果我的问题正确,您的用户可以在您的输入框中指定一个完整的 Lucene 查询字符串,对吗?如果是这样,它对用户体验不是很友好,因为正如您所看到的,您的用户不知道您选择了哪些字段名称。有多少个字段是可搜索的,或者哪些是您想要搜索的所有字段?

标签: elasticsearch nest


【解决方案1】:

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

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

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

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

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

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

只是为了提及这一点但无论如何我不推荐它,我认为您可以使用script 来做任何您想做的事情使用 Groovy 中的字段名称。但是,这意味着您不会使用 Elasticsearch 的真正力量

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

【讨论】:

    【解决方案2】:

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

    实际上,用户界面可以在他们键入时即时执行此操作并帮助他们选择正确的选项。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 2017-04-25
        • 2015-10-21
        • 1970-01-01
        • 1970-01-01
        • 2018-08-05
        • 2016-11-12
        相关资源
        最近更新 更多