I have to write a query that has to return if my object has a parking or not. In the index the parking are stored as integer, to indicate how many parking places belong to the object. In the query the property is boolean, to indicate does we want or not to search if the object has parking places.
I tried this with conditional query, but as I see now it is wrong way.
My question is, how to write the HasParking()
function, where I can check if the field value is greater then 0, that indicates that the object has parking place(s).
This is how I started:
public partial class ElasticSearchService
{
private List<Func<QueryContainerDescriptor<AdvertisementObjectEntityExtended>, QueryContainer>> filters = null;
public async Task<List<AdvertisementObjectEntityExtended>> AdvancedSearchAsync(AdvancedFilter filter)
{
filters = new List<Func<QueryContainerDescriptor<AdvertisementObjectEntityExtended>, QueryContainer>>();
string location = !string.IsNullOrEmpty(filter.LocationSuggestion.SubLocation) ? filter.LocationSuggestion.SubLocation : filter.LocationSuggestion.City;
HasOrientation(filter.Orientations);
HasStructure(filter.Structures);
HasHeatingType(filter.HeatingTypes);
HasDescription(filter.ObjectDescriptions);
HasPropertyCondition(filter.PropertyConditions);
HasBelongingSurface(filter.BelongingSurfaces);
ISearchResponse<AdvertisementObjectEntityExtended> result = await Client.SearchAsync<AdvertisementObjectEntityExtended>(s => s
.Index(ElasticClientFactorySettings.AdvertisementObjectIndex)
.Query(q =>
q.QueryString(qs => qs.DefaultField(f => f.Location.ToLower()).Query($"{location.ToLower()}")) &&
q.MatchPhrase(x => x.Field(t => t.SubCategoryKey).Query(filter.Subcategory.Key)) &&
q.Term(t => t.IsRentable, filter.IsRentable) &&
q.Term(t => t.Garage, filter.Garage) &&
q.Term(t => t.WiFi, filter.WiFi) &&
q.Term(t => t.Elevator, filter.Elevator) &&
q.Term(t => t.FurnishState, filter.FurnishState) &&
q.Term(t => t.Deposit, filter.Deposit) &&
q.Term(t => t.Duplex, filter.Duplex) &&
q.Term(t => t.SeparateKitchen, filter.SeparateKitchen) &&
q.Term(t => t.LaundryAndDryingRoom, filter.LaundryAndDryingRoom) &&
q.Term(t => t.Basement, filter.Basement) &&
q.Term(t => t.Terrace, filter.Terrace) &&
q.Term(t => t.Balcony, filter.Balcony) &&
q.Term(t => t.Loggia, filter.Loggia) &&
q.Term(t => t.FrenchBalcony, filter.FrenchBalcony) &&
q.Term(t => t.EnergyPassport, filter.EnergyPassport) &&
q.Term(t => t.ImmediatelyHabitable, filter.ImmediatelyHabitable) &&
q.Term(t => t.VATRefount, filter.VATRefount) &&
q.Term(t => t.ExchangePossible, filter.ExchangePossible) &&
q.Term(t => t.Filed, filter.Filed) &&
q.Term(t => t.Mortgaged, filter.Mortgaged) &&
q.Term(t => t.Longue, filter.Longue) &&
q.Term(t => t.Wardrobe, filter.Wardrobe) &&
q.Term(t => t.Penthouse, filter.Penthouse) &&
q.Term(t => t.WarmWater, filter.WarmWater) &&
q.Term(t => t.Intercom, filter.Intercom) &&
q.Term(t => t.Climate, filter.Climate) &&
q.Term(t => t.Phone, filter.Phone) &&
q.Term(t => t.Alarm, filter.Alarm) &&
q.Term(t => t.Security, filter.Security) &&
q.Term(t => t.SecurityDoor, filter.SecurityDoor) &&
q.Term(t => t.VideosSurveillance, filter.VideosSurveillance) &&
q.Term(t => t.CableTV, filter.CableTV) &&
q.Term(t => t.Fireplace, filter.Fireplace) &&
q.Term(t => t.BestDeal, filter.IsBestDeal) &&
q.Range(r => r.Field(f => f.Price)
.GreaterThanOrEquals(filter.PriceFrom)
.LessThanOrEquals(filter.PriceTo)) &&
q.Range(r => r.Field(f => f.Quadrature)
.GreaterThanOrEquals(filter.QuadratureFrom)
.LessThanOrEquals(filter.QuadratureTo)) &&
q.Range(r => r.Field(f => f.Badrooms)
.GreaterThanOrEquals(filter.BadroomsFrom)
.LessThanOrEquals(filter.BadroomsTo)) &&
q.Bool(bq => bq.Filter(filters)))
.Sort(s =>
s.Field(f => SortByFilter(f, filter.Sort))));
return result.Documents.ToList();
}
private QueryBase HasParking(bool value)
{
return !value ?
null :
+new TermQuery
{
Field = Infer.Field<AdvertisementObjectEntityExtended>(f => f.Parking),
Value = 1
};
}
private QueryBase HasShowcase3D()
{
throw new NotImplementedException();
}
private QueryBase HasImages()
{
throw new NotImplementedException();
}
private QueryBase HasVideoURL()
{
throw new NotImplementedException();
}
private void HasOrientation(AdvertisementObjectOrientation[] orientations)
{
if (orientations != null && orientations.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.Orientation).Terms(orientations)));
}
}
private void HasStructure(AdvertisementObjectStructure[] structures)
{
if (structures != null && structures.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.Structure).Terms(structures)));
}
}
private void HasHeatingType(AdvertisementObjectHeating[] heatingTypes)
{
if (heatingTypes != null && heatingTypes.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.HeatingType).Terms(heatingTypes)));
}
}
private void HasDescription(AdvertisementObjectDescription[] descriptions)
{
if (descriptions != null && descriptions.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.ObjectDescription).Terms(descriptions)));
}
}
private void HasPropertyCondition(AdvertisementObjectPropertyCondition[] propertyConditions)
{
if (propertyConditions != null && propertyConditions.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.PropertyCondition).Terms(propertyConditions)));
}
}
private void HasBelongingSurface(AdvertisementObjectBelongingSurfaces[] belongingSurfaces)
{
if (belongingSurfaces != null && belongingSurfaces.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.BelongingSurfaces).Terms(belongingSurfaces)));
}
}
}
You can have a method like this, which returns the NumericRangeQuery
private NumericRangeQuery HasParking(bool value)
{
if(value)
{
return new NumericRangeQuery
{
Name = "named_query",
Boost = 1.1, // Remove the boost if you do not need it
Field = "parking",
GreaterThan = 0
};
}
return null;
}
Now hook this method into your chain of filters as this returns a NumericRangeQuery
object as a result. This should be called from the location we want to add the range query based on the boolean
field that you are passing into this method and accordingly this gets added conditionally to the query that NEST client generates.
You can hook this query with a call similar to the one below
q.Range(r => HasParking(<param>));