我使用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();
PS:我跟着this guide创建了
修改
答案 0 :(得分:2)
There's a couple of things that I can see that may help here:
x => x.Question
will serialize to "question"
. Looking at your mapping however, field names in Elasticsearch are Pascal cased, so what the client is doing will not match what's in Elasticsearch.You can change how NEST serializes POCO property names by using .DefaultFieldNameInferrer(Func<string, string>)
on ConnectionSettings
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);
As Rob mentioned in the comments, a term query does not analyze the query input. When executing a term query against a field that is analyzed at index time then, in order to get matches, the query text that you pass to the term query would need to take the analysis that is applied at index time into account. For example,
Question
is analyzed with the Standard AnalyzerQuestion
value of "What's the Question?"
will be analyzed and indexed as tokens "what's"
, "the"
and "question"
"what's"
, "the"
or "question"
to be a matchA match query, unlike a term query, does analyze the query input, so the output of the search analysis will be used to find matches. In conjunction with Pascal casing highlighted in 1., you should now get documents returned.
You can also have the best of both worlds in Elasticsearch i.e. analyze input at index time for full-text search functionality as well as index input without analysis to get exact matches. This is done with multi-fields and here is an example of creating a mapping that indexes Question
properties as both analyzed and not analyzed
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()
)
)
)
)
)
)
);
The mapping for this looks like
{
"mappings": {
"faq": {
"properties": {
"Question": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
The "raw"
sub field under the "Question"
field will index the value of the Question
property without any analysis i.e. verbatim. This sub field can now be used in a term query to find exact matches
client.Search<Faq>(s => s
.Query(q => q
.Term(f => f.Question.Suffix("raw"), "What's the Question?")
)
);
which find matches for the previous example.