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);
这会将您的字段存储为小写。然后当您查询时,只需将用户提供的所有字段强制为小写即可。
如果您不是从头开始,则必须重新填充数据以保持命名策略的统一。
我将 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);
这会将您的字段存储为小写。然后当您查询时,只需将用户提供的所有字段强制为小写即可。
如果您不是从头开始,则必须重新填充数据以保持命名策略的统一。