I am new to the elastic search, I have done a bit of research but I could not find the right answer which fits to my requirement. The below query return the results of searched term and surrounding suburbs results together with the filter condition and I want to sort them individually, term search should always be on the top and surrounding suburbs at the bottom, I have done the aggregation so I know the count of search term results.
With the query I am getting something like, if search with the term : Kotara (which is a suburb), I get the result for that suburb and also surrounding suburbs with in the range of 5km. propertyId:1, address.suburb: "charlestown", price:500,000 (1 record which is surrounding suburb) propertyId:2, address.suburb: "kotara", price:500,000 (2nd record, searched term) PropertyId:14, address.suburb:"Newcastle", price:400,000(3rd record, surrounding), propertyId: 4, address.suburb: "kotara", price:200,000 (4th record, searched term)
But I want the result like propertyId:2, address.suburb: "kotara", price:500,000 (1st record, searched term) propertyId: 4, address.suburb: "kotara", price:200,000 (2nd record, searched term)
propertyId:1, address.suburb: "charlestown", price:500,000 (3rd record which is surrounding suburb) PropertyId:14, address.suburb:"Newcastle", price:400,000(3rd record, surrounding)
All the "searched term" results should be at the top of the sorting then all the other sorting conditions should come
FilterContainer termFilters = new FilterContainer();
FilterContainer refineFilters = new FilterContainer();
FilterContainer surroundingFilters = new FilterContainer();
var exactMatches = await _elasticClient.SearchAsync(s => s
.From(requestedPage * request.PageSize)
.Size(request.PageSize > 0 ? request.PageSize : 20)
.Filter(f =>
{
refineFilters = f.Term(t => t.Status, "current");
FilterContainer filter = new FilterContainer();
if (request.Terms != null && request.Terms.Any())
{
foreach (var term in request.Terms)
{
FilterContainer termFilter = new FilterContainer();
termFilter = f.Term(x => x.Address.Suburb, term.Term.ToLower());
termFilters |=
(termFilter
&& (f.Term(x => x.Address.StateAbbr, term.State.ToLower())
|| f.Term(x => x.Address.State, term.State.ToLower())));
if (request.SurroundingSuburbs)
{
surroundingFilters |= (f.GeoDistance(g => g.Address.Location, geoDistanceFilterDescriptor => geoDistanceFilterDescriptor
.Location(term.Location.Latitude, term.Location.Longitude)
.Distance("5km")
.DistanceType(GeoDistance.Arc)));
}
}
filter = filter && (termFilters || surroundingFilters);
}
if (request.ExcludeUnderOffer)
{
refineFilters &= f.Term(x => x.UnderOffer, false);
}
filter = filter && (refineFilters);
return filter;
})
.Aggregations(ag =>
{
return ag.Filter("SearchTermMatchCount", st => st
.Filter(
f =>
{
return termFilters && refineFilters;
}).Aggregations(sag =>
{
return sag.Terms("SearchTermMatch", t => t.Field(sf => sf.Address.Suburb).OrderAscending("_term"));
} ));
})
.SortGeoDistance(sgd =>
{
if (request.Sort == Csn.Dto.Homesales.Enums.SortOrder.Distance)
{
return sgd.OnField(x => x.Address.Location)
.Order(Nest.SortOrder.Ascending)
.Unit(GeoUnit.Kilometers)
.Mode(SortMode.Min)
.DistanceType(GeoDistance.Plane)
.PinTo(firstTermLatForSort, firstTermLngForSort);
}
else
{
return null;
}
})
.Sort(st =>
{
switch (request.Sort)
{
case Csn.Dto.Homesales.Enums.SortOrder.LatestListing:
return st.OnField(x => x.DateCreated).Descending();
case Csn.Dto.Homesales.Enums.SortOrder.OldestListing:
return st.OnField(x => x.DateCreated).Ascending();
case Csn.Dto.Homesales.Enums.SortOrder.PriceHighest:
return st.OnField(x => x.Price.Price).Descending();
case Csn.Dto.Homesales.Enums.SortOrder.PriceLowest:
return st.OnField(x => x.Price.Price).Ascending();
default:
{
if (request.Sort != Csn.Dto.Homesales.Enums.SortOrder.Distance)
{
return st.OnField(x => x.AdPriority).Descending();
}
else
{
return null;
}
}
}
}
)
);
response.Matches = exactMatches.Documents.ToList();
response.Count = exactMatches.Total;
var aggregation = (SingleBucket)exactMatches.Aggregations.Where(a=>a.Key == "SearchTermMatchCount").Select(a => a.Value);
response.SearchTermMatchCount = aggregation.DocCount;