Я использую NEST для запроса индекса ElasticSearch с помощью вложенного запроса, и все работает, но меня смущает цель одной строки кода в запросе. Прежде чем идти дальше, я предоставлю все объекты и сам запрос.
Вот объект, который соответствует индексу "country"
.
[ElasticsearchType(Name = "country")]
public class CountrySearchDto : ISearchIndex {
public int Id {get; set;}
public string Name { get; set; }
public string IsoCode {get; set;}
public string CountryCode{get; set;}
[Nested]
public List<AreaSearchDto> Areas {get; set;}
}
}
Вот объект, который соответствует индексу "area"
.
public class AreaSearchDto : ISearchIndex{
public int Id {get; set;}
public string Name { get; set; }
public string GuideUrl { get; set; }
}
Как видите, внутри индекса country
есть areas
. Сделанный мной запрос используется для поиска стран по областям, вложенным внутрь.
Вот запрос.
var searchResults = await _searchClient.SearchAsync<CountrySearchDto>(s => s
.Index("country")
.Query(q => q
.Nested(c => c
.Path(p => p.Areas)
.Query(nq => nq
.Term(t => t.Areas.FirstOrDefault().Name, searchTerm) // Where searchTerm is a string like "Sydney" or "London"
))
)
);
Я понимаю, как работает вложенный запрос, и он правильно получает всю необходимую мне информацию. Но что делает эта строка кода?
.Term(t => t.Areas.FirstOrDefault().Name, searchTerm) // Where searchTerm is a string like "Sydney" or "London"
Разве FirstOrDefault()
не ограничит запрос только для первого значения Areas, а не для всех? Очевидно, что это не так, но мне интересно, может ли кто-нибудь объяснить, что здесь происходит.
t => t.Areas.FirstOrDefault().Name
— это лямбда-выражение, которое преобразуется в имя поля для использования в запросе Elasticsearch. Это не казнен как таковой, чтобы получить значение имени первой области, а скорее пройти, чтобы создать строку для имени поля, на которое нацелен терм-запрос. Как отмечает Хохштейн в комментариях, целью запроса термина внутри вложенного запроса является поле AreaSearchDto
как путь от корня документа, представленного типом CountrySearchDto
, к которому относится поисковый запрос. Использование лямбда-выражения для выполнения этого обхода позволяет вам использовать преимущества типов.
С searchTerm
из "searchTerm"
сгенерированный запрос будет
POST http://localhost:9200/country/country/_search
{
"query": {
"nested": {
"path": "areas",
"query": {
"term": {
"areas.name": {
"value": "searchTerm"
}
}
}
}
}
}
Лямбда-выражение было преобразовано в строку "areas.name"
t.Areas — это массив Areas, но вам нужно предоставить объект Areas в этой лямбде, поэтому он используется для доступа к объекту Areas.