使用 NEST 的 Elasticsearch 查询不起作用
Elasticsearch query with NEST don't work
我正在使用 Microsoft SQL Server Management Studio 和 ElasticSearch 2.3.4 以及 ElasticSearch-jdbc-2.3.4.1,并且我将 ES 与我的 mssql 服务器相关联。一切正常,但是当我在我的 MVC 程序上使用 NEST 进行查询时,结果为空。当我在我的 search
属性中放入一个空字符串时,我得到了元素,但是当我尝试用一些过滤器填充它时,我得到一个空结果。有人可以帮我吗?提前致谢。
C#:
const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer));
settings.DefaultIndex("tiky");
settings.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"));
ElasticClient client = new ElasticClient(settings);
var response = client.Search<DAL.Faq>(s => s.Query(q => q.Term(x => x.Question, search)));
var result = response.Documents.ToList();
DAL:
邮递员:
PS: 我跟着 this guide 创建了它
编辑:
索引映射:
我看到的一些内容可能对您有所帮助:
- 默认情况下,NEST camel 将 POCO 属性 名称序列化为请求中查询 JSON 的一部分,因此
x => x.Question
将序列化为 "question"
。然而,查看您的映射,Elasticsearch 中的字段名称是 Pascal 大小写的,因此客户端所做的与 Elasticsearch 中的不匹配。
您可以通过在 ConnectionSettings
上使用 .DefaultFieldNameInferrer(Func<string, string>)
来更改 NEST 序列化 POCO 属性 名称的方式
const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer))
.DefaultIndex("tiky");
.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"))
// pass POCO property names through verbatim
.DefaultFieldNameInferrer(s => s);
ElasticClient client = new ElasticClient(settings);
正如 Rob 在评论中提到的,a term query 不分析 查询输入。当针对在索引时分析的字段执行术语查询时,为了获得匹配,您传递给术语查询的查询文本需要考虑在索引时应用的分析。例如,
Question
用the Standard Analyzer 分析
"What's the Question?"
的 Question
值将作为标记 "what's"
、"the"
和 "question"
进行分析和索引
- 术语查询需要输入
"what's"
、"the"
或 "question"
才能匹配
匹配查询与术语查询不同,它会分析查询输入,因此搜索分析的输出将用于查找匹配项。结合 1. 中突出显示的 Pascal 大小写,您现在应该可以返回文档。
您还可以在 Elasticsearch 中两全其美,即在索引时分析输入以获得全文搜索功能,以及在不分析的情况下索引输入以获得精确匹配。这是通过 multi-fields 完成的,这里是创建一个映射的示例,该映射将 Question
属性索引为已分析和未分析的
public class Faq
{
public string Question { get; set; }
}
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex)
.DefaultFieldNameInferrer(s => s);
var client = new ElasticClient(connectionSettings);
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<Faq>(mm => mm
// let NEST infer mapping from the POCO
.AutoMap()
// override any inferred mappings explicitly
.Properties(p => p
.String(s => s
.Name(n => n.Question)
.Fields(f => f
.String(ss => ss
.Name("raw")
.NotAnalyzed()
)
)
)
)
)
)
);
这个映射看起来像
{
"mappings": {
"faq": {
"properties": {
"Question": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
"Question"
字段下的 "raw"
子字段将索引 Question
属性 的值,无需任何分析,即逐字记录。此子字段现在可用于术语查询以查找完全匹配项
client.Search<Faq>(s => s
.Query(q => q
.Term(f => f.Question.Suffix("raw"), "What's the Question?")
)
);
其中找到与上一个示例匹配的项。
我正在使用 Microsoft SQL Server Management Studio 和 ElasticSearch 2.3.4 以及 ElasticSearch-jdbc-2.3.4.1,并且我将 ES 与我的 mssql 服务器相关联。一切正常,但是当我在我的 MVC 程序上使用 NEST 进行查询时,结果为空。当我在我的 search
属性中放入一个空字符串时,我得到了元素,但是当我尝试用一些过滤器填充它时,我得到一个空结果。有人可以帮我吗?提前致谢。
C#:
const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer));
settings.DefaultIndex("tiky");
settings.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"));
ElasticClient client = new ElasticClient(settings);
var response = client.Search<DAL.Faq>(s => s.Query(q => q.Term(x => x.Question, search)));
var result = response.Documents.ToList();
DAL:
邮递员:
PS: 我跟着 this guide 创建了它
编辑:
索引映射:
我看到的一些内容可能对您有所帮助:
- 默认情况下,NEST camel 将 POCO 属性 名称序列化为请求中查询 JSON 的一部分,因此
x => x.Question
将序列化为"question"
。然而,查看您的映射,Elasticsearch 中的字段名称是 Pascal 大小写的,因此客户端所做的与 Elasticsearch 中的不匹配。
您可以通过在 ConnectionSettings
.DefaultFieldNameInferrer(Func<string, string>)
来更改 NEST 序列化 POCO 属性 名称的方式
const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer))
.DefaultIndex("tiky");
.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"))
// pass POCO property names through verbatim
.DefaultFieldNameInferrer(s => s);
ElasticClient client = new ElasticClient(settings);
正如 Rob 在评论中提到的,a term query 不分析 查询输入。当针对在索引时分析的字段执行术语查询时,为了获得匹配,您传递给术语查询的查询文本需要考虑在索引时应用的分析。例如,
Question
用the Standard Analyzer 分析
"What's the Question?"
的Question
值将作为标记"what's"
、"the"
和"question"
进行分析和索引
- 术语查询需要输入
"what's"
、"the"
或"question"
才能匹配
匹配查询与术语查询不同,它会分析查询输入,因此搜索分析的输出将用于查找匹配项。结合 1. 中突出显示的 Pascal 大小写,您现在应该可以返回文档。
您还可以在 Elasticsearch 中两全其美,即在索引时分析输入以获得全文搜索功能,以及在不分析的情况下索引输入以获得精确匹配。这是通过 multi-fields 完成的,这里是创建一个映射的示例,该映射将 Question
属性索引为已分析和未分析的
public class Faq
{
public string Question { get; set; }
}
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex)
.DefaultFieldNameInferrer(s => s);
var client = new ElasticClient(connectionSettings);
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<Faq>(mm => mm
// let NEST infer mapping from the POCO
.AutoMap()
// override any inferred mappings explicitly
.Properties(p => p
.String(s => s
.Name(n => n.Question)
.Fields(f => f
.String(ss => ss
.Name("raw")
.NotAnalyzed()
)
)
)
)
)
)
);
这个映射看起来像
{
"mappings": {
"faq": {
"properties": {
"Question": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
"Question"
字段下的 "raw"
子字段将索引 Question
属性 的值,无需任何分析,即逐字记录。此子字段现在可用于术语查询以查找完全匹配项
client.Search<Faq>(s => s
.Query(q => q
.Term(f => f.Question.Suffix("raw"), "What's the Question?")
)
);
其中找到与上一个示例匹配的项。