Skip to content

Instantly share code, notes, and snippets.

@gzigzigzeo
Last active August 29, 2015 13:59
Show Gist options
  • Save gzigzigzeo/10825032 to your computer and use it in GitHub Desktop.
Save gzigzigzeo/10825032 to your computer and use it in GitHub Desktop.
def build_query(options = {})
query = {
sort: sort(options),
query: {
filtered: {
query: {
bool: {
must: address_or_keywords(options),
should: fulltext(options)
}
},
filter: {
and: filter(options)
}
}
},
aggregations: clusterize(options)
}
highlight(query, address: {}) if options[:highlight]
paginate(query, options)
Elastic::QuerySanitizer.sanitize(query)
end
private
def filter(options)
[
*terms(options),
*ranges(options),
*rooms(options),
*price(options),
on_map(options),
only_with_photo(options),
not_id(options),
polygon(options),
extra_options(options),
bbox(:lat_lng, options)
]
end
def sort(options)
sort_by_lat_lng(options) ||
sort_by_column(options) ||
sort_by_rank
end
def sort_by_lat_lng(options)
if options[:lat_lng].present?
{
_geo_distance: {
lat_lng: options[:lat_lng], order: :asc, unit: :km
}
}
end
end
def sort_by_column(options)
if options[:sort_column] && options[:sort_direction]
{
options[:sort_column].to_sym => {
order: options[:sort_direction].to_sym,
missing: :_last
}
}
end
end
def sort_by_rank
{ rank: { order: :desc, missing: :_last } }
end
def address_or_keywords(options)
[
{ match: { address: { query: options[:address], operator: :and } } },
{ match: { keywords: options[:keywords] } }
]
end
def fulltext(options)
if options[:query]
[
{ match: { address: options[:query] } },
{ match: { keywords: options[:query] } },
{ term: { id: options[:query] =~ INTEGER_FORMAT && options[:query] } }
]
end
end
def terms(options)
generate_terms(
options.slice(
:author_id, :author_type, :city_id, :advert_type,
:property_type, :addressing_id, :addressing_border_id,
:pay_type, :material, :kind, :sell_type, :flat_plan,
:commercial_type, :metro
)
)
end
def ranges(options)
[
{ range: { plot_area: { gte: options[:plot_area_from] } } },
{ range: { area: { gte: options[:area_from] } } },
{ range: { floor: { gte: options[:floor_from] } } }
]
end
def rooms(options)
rooms_key = if options[:property_type] == 'house'
:bedrooms
else
:rooms
end
[
{ terms: { rooms_key => options[:rooms_range] } },
{ terms: { rooms_to_sell: options[:rooms_to_sell_range] } }
]
end
def price(options)
value = options[:price_rub_to].to_i
if value > 0
key_field = if options[:price_type] == 'total' || options[:price_type].blank?
:price_rub
else
:price_rub_perm
end
[
{ range: { key_field => { lte: value } } },
{ term: { price_per_request: false } }
]
end
end
def clusterize(options)
if options[:clusterize]
{
grid: {
geohash_grid: {
field: 'lat_lng',
precision: options[:precision],
size: 500
},
aggregations: {
avg_lat: { avg: { field: 'lat_lng.lat' } },
avg_lon: { avg: { field: 'lat_lng.lon' } },
rooms: { max: { field: 'rooms'} },
id: { max: { field: 'id' } },
price: { max: { field: 'price_rub' } }
}
}
}
end
end
@anthonator
Copy link

What is Elastic::QuerySanitizer.sanitize?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment