Elasticsearch NEST library, wired behavior

2019-09-01 07:00发布

问题:

Using NEST .NET library I worte following query.

var result = client.Search<StudenntBrief>(s => s.Type("Students").Query(q => q.Term("Name","Robert")));

It worked fine and got 7 results.

Instead of using maigic string to represent field i tried to use expression as follows.

var result = client.Search<StudenntBrief>(s => s.Type("Students").Query(q => q.Term(t => t.Name,"Robert")));

I found zero results.

Here is one more example.

Works.

var result = client.Search<StudenntBrief>(s => s.Type("Students").Query(q => q.MultiMatch(a => a.OnFields(new List<string{"Name"}).Query("Robert"))));

Doesn't works.

var result = client.Search<StudenntBrief>(s => s.Type("Students").Query(q => q.MultiMatch(a => a.OnFields(f=> f.Name).Query("Robert"))));

I am wondering why query using expression to represent field is not working.

回答1:

bsarkar's answer is partially correct.

NEST camelCases field names by default. There are a few ways to customize this behavior.

You can override the default camelCasing by specifying your own property name inferrer: How to disable camel casing Elasticsearch field names in NEST?. This approach will apply to all fields and all types.

Another approach is to specify the field names explicitly by either using the ElasticyProperty attribute as bsarkar mentioned, or using the newer fluent property mapping API that was added in version 1.3: https://github.com/elasticsearch/elasticsearch-net/pull/1062

settings.MapPropertiesFor<MyClass>(props => props
    .Rename(p => p.Foo, "bar")
);

Hope that helps.



回答2:

This happens because Nest serealizes field names to lowercase by default. Hence t.Name actually serializes to "name" which I guess does not exist in the mapping Students (Note: field names are case-sensitive in Elasticsearch) and hence no results. Whereas when you directly use "Name", it works. One way to fix this is to decorate the Name field in StudenntBrief class with attribute [ElasticProperty(Name = "Name")].

Even better, you can decorate class StudenntBrief with attribute [ElasticType(Name = "Students")]. That way you can also avoid having to specify Type explicitly when building the search request using Nest.