Skip to content

Commit

Permalink
Add more filters
Browse files Browse the repository at this point in the history
  • Loading branch information
egemenzeytinci committed Feb 11, 2022
1 parent 3169841 commit 41ae297
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 77 deletions.
1 change: 1 addition & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ max-args=10
generated-members=
# elasticsearch-dsl
s.source,
s.sort,
# sqlalchemy
session.commit,
session.query,
Expand Down
13 changes: 11 additions & 2 deletions assets/js/movie.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,22 @@
const cy = document.querySelectorAll('input[name=year]:checked');
const years = [...cy].map(c => c.value);

// Checked score
const cs = document.querySelector('input[name=score]:checked');

// Checked number of votes
const cn = document.querySelector('input[name=num_votes]:checked');

const xhr = new XMLHttpRequest();

var formData = new FormData();

// Form data for the request
formData.append('genres', genres);
formData.append('years', years);
if (genres.length > 0) formData.append('years', years);
if (years.length > 0) formData.append('years', years);
if (cs) formData.append('score', cs.value)
if (cn) formData.append('num_votes', cn.value)

formData.append('page', page);

xhr.open('POST', '/movie/search', false);
Expand Down
1 change: 1 addition & 0 deletions elastic/model/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Basic(Document):
start_year = Integer()
average_rating = Float()
num_votes = Integer()
score = Float()
title_type = Keyword()

class Index:
Expand Down
46 changes: 27 additions & 19 deletions elastic/service/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,6 @@ class ElasticBasicService:
def __init__(self):
self._name = 'basic'

self._year_map = {
'2020s': [2020, 2029],
'2010s': [2010, 2019],
'2000s': [2000, 2009],
'1990s': [1990, 1999],
'1980s': [1980, 1989],
'1970s': [1970, 1979],
'1960s': [1960, 1969],
'1950s': [1950, 1959],
'b1950': [1800, 1949]
}

def _save(self, basics):
"""
Save data to basic index
Expand Down Expand Up @@ -71,6 +59,7 @@ def save_all(self):
b.genres = r.basic.genres
b.start_year = r.basic.start_year
b.average_rating = r.rating.average_rating
b.score = r.rating.average_rating * r.rating.num_votes
b.num_votes = r.rating.num_votes
b.title_type = r.basic.title_type

Expand All @@ -80,7 +69,16 @@ def save_all(self):

offset += limit

def search(self, genres, years, page=1, size=12, exact=True):
def search(
self,
genres,
years,
score,
num_votes,
page=1,
size=12,
exact=True
):
"""
Search on basic index
Expand All @@ -103,27 +101,37 @@ def search(self, genres, years, page=1, size=12, exact=True):

ranges = []

# filter by year
for year in years:
lower, upper = self._year_map[year]

# filter by year
year_filter = {
'gte': lower,
'lte': upper
'gte': int(year) - 9,
'lte': int(year)
}

range_query = Q('range', start_year=year_filter)

ranges.append(range_query)

filters = [
Q('bool', should=ranges)
Q('bool', should=ranges),
]

# filter by imdb score
score_filter = Q('range', average_rating={'gte': float(score)})
filters.append(score_filter)

# filter by number of votes
vote_filter = Q('range', num_votes={'gte': num_votes})
filters.append(vote_filter)

# search object by limit and offset
from_ = (page - 1) * size

s = Search(using=es, index=self._name).extra(from_=from_, size=size)

# sort by score (num_votes * average_rating) descending
s = s.sort('-score')

# set query
s.query = Q('bool', must=musts, filter=filters)

Expand Down
1 change: 1 addition & 0 deletions server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
app.config['SECRET_KEY'] = config.app.secret_key

# update jinja environments
app.jinja_env.globals['f_range'] = Ninja.float_range
app.jinja_env.globals['f_minute'] = Ninja.format_minutes
app.jinja_env.globals['unescape'] = Ninja.unescape
77 changes: 33 additions & 44 deletions template/movie.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,40 @@ <h5>Filter by genre</h5>
<div class="row mt-4">
<h5>Filter by year</h5>
<div class="form-check">
<input class="btn-check" name="year" type="checkbox" value="2020s" id="2020s"/>
<label class="btn btn-outline-secondary mt-2" for="2020s">
2020s
</label>
{% for i in range(2029, 1939, -10) %}
{% set button_text = (i - 9) | string + 's' %}

<input class="btn-check" name="year" type="checkbox" value="2010s" id="2010s"/>
<label class="btn btn-outline-secondary mt-2" for="2010s">
2010s
</label>
{% if i == 1949 %}
{% set button_text = 'Before 1950' %}
{% endif %}

<input class="btn-check" name="year" type="checkbox" value="2000s" id="2000s"/>
<label class="btn btn-outline-secondary mt-2" for="2000s">
2000s
</label>

<input class="btn-check" name="year" type="checkbox" value="1990s" id="1990s"/>
<label class="btn btn-outline-secondary mt-2" for="1990s">
1990s
</label>

<input class="btn-check" name="year" type="checkbox" value="1980s" id="1980s"/>
<label class="btn btn-outline-secondary mt-2" for="1980s">
1980s
</label>

<input class="btn-check" name="year" type="checkbox" value="1970s" id="1970s"/>
<label class="btn btn-outline-secondary mt-2" for="1970s">
1970s
</label>

<input class="btn-check" name="year" type="checkbox" value="1960s" id="1960s"/>
<label class="btn btn-outline-secondary mt-2" for="1960s">
1960s
</label>

<input class="btn-check" name="year" type="checkbox" value="1950s" id="1950s"/>
<label class="btn btn-outline-secondary mt-2" for="1950s">
1950s
</label>

<input class="btn-check" name="year" type="checkbox" value="b1950" id="b1950"/>
<label class="btn btn-outline-secondary mt-2" for="b1950">
Before 1950
</label>
<input class="btn-check" name="year" type="checkbox" value="{{ i }}" id="{{ i }}s"/>
<label class="btn btn-outline-secondary mt-2" for="{{ i }}s">
{{ button_text }}
</label>
{% endfor %}
</div>
</div>
<div class="row mt-4">
<h5>Filter by IMDB score</h5>
<div class="form-check">
{% for i in f_range(5, 9.5, 0.5) %}
<input class="btn-check" name="score" type="radio" value="{{ i }}" id="{{ i }}+"/>
<label class="btn btn-outline-secondary mt-2" for="{{ i }}+">
{{ i }}+
</label>
{% endfor %}
</div>
</div>
<div class="row mt-4">
<h5>Filter by number of votes</h5>
<div class="form-check">
{% for i in range(5000, 30000, 5000) %}
<input class="btn-check" name="num_votes" type="radio" value="{{ i }}" id="{{ i }}+"/>
<label class="btn btn-outline-secondary mt-2" for="{{ i }}+">
{{ i }}+
</label>
{% endfor %}
</div>
</div>
<button type="button" class="btn btn-primary btn-apply">
Expand Down Expand Up @@ -96,8 +86,7 @@ <h5>Filter by year</h5>
{% endfor %}
</div>
<nav class="visually-hidden nav-pagination mb-5">
<ul class="pagination ul-pagination">
</ul>
<ul class="pagination ul-pagination"></ul>
</nav>
</div>
{% endblock %}
Expand Down
14 changes: 14 additions & 0 deletions util/ninja.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import html
import numpy as np


class Ninja:
@staticmethod
def float_range(lower, upper, step):
"""
Float range function
:param int lower: lower point
:param int upper: upper point
:param float step: step value
:return: list of values by lower, upper and step values
:rtype: list
"""
return list(np.arange(lower, upper, step))

@staticmethod
def format_minutes(minutes):
"""
Expand Down
3 changes: 3 additions & 0 deletions validation/custom/field_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def _value(self):
return ''

def process_formdata(self, valuelist):
if self.data:
valuelist = self.data

if valuelist:
self.data = [x.strip() for x in valuelist[0].split(',')]
else:
Expand Down
44 changes: 32 additions & 12 deletions validation/movie.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
from validation import ServiceForm
from validation.custom import CommaSeparatedField
from wtforms import IntegerField, StringField
from wtforms.validators import DataRequired, NumberRange
from wtforms import DecimalField, IntegerField, StringField
from wtforms.validators import DataRequired, Optional, NumberRange


class MovieListForm(ServiceForm):
genres = CommaSeparatedField(
StringField(
'genres',
validators=[
DataRequired(message='The genres field is required.')
]
)
validators=[Optional()]
),
default=['Drama']
)

years = CommaSeparatedField(
StringField(
IntegerField(
'years',
validators=[
DataRequired(message='The years field is required.')
]
)
validators=[Optional()]
),
default=['1979, 1989, 1999, 2009']
)

score = DecimalField(
label='score',
validators=[
Optional(),
NumberRange(min=5.0, max=9.0, message='The score must be between 5.0 and 9.0.')
],
default=8.0
)

num_votes = IntegerField(
label='num_votes',
validators=[
Optional(),
NumberRange(
min=5000,
max=25000,
message='The number of votes must be between 5000 and 25000.'
)
],
default=25000
)

page = IntegerField(
label='page',
validators=[
DataRequired(),
DataRequired('The page number is required.'),
NumberRange(min=1, message='The page number must be at least 1.')
]
)
2 changes: 2 additions & 0 deletions web/movie.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def search():
result = ebs.search(
genres=form.genres.data,
years=form.years.data,
score=form.score.data,
num_votes=form.num_votes.data,
page=form.page.data,
exact=False
)
Expand Down

0 comments on commit 41ae297

Please sign in to comment.