Skip to content

Commit

Permalink
Filtering... 201
Browse files Browse the repository at this point in the history
  • Loading branch information
davedash committed May 17, 2011
1 parent b0aceee commit ccc0a11
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
30 changes: 30 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,36 @@ Filters
``S('taco trucks').filter(style='korean')`` will do a query for "taco trucks"
filtering on the attribute ``style``. This is how we find Korean Taco Trucks.

*Note*: Repeat calls to ``.filter`` will reset the filters.


Multiple Filters
~~~~~~~~~~~~~~~~

``S('taco trucks').filter(style='korean', price='FREE')``
will do a query for "taco trucks" that are
"korean" style and have a price of
"FREE".

This is however equivalent to the more succinct::

S('taco trucks', style='korean', price='FREE')


Complicate Filtering
~~~~~~~~~~~~~~~~~~~~

Sometimes you want something complicated. For that we have the ``F`` (filter)
object.

``S('taco trucks').filter(F(style='korean')|F(style='thai'))``
will find you "thai" or "korean" style taco trucks.

Let's say you only want "korean" tacos if you can get it for "FREE" or "thai"
tacos at any price::

S('taco trucks').filter(F(style='korean', price='FREE')|F(style='thai'))


Facets
------
Expand Down
31 changes: 29 additions & 2 deletions elasticutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ def _process_filters(filters):
return qfilters[0]


class F(object):
"""
Filter objects.
"""
def __init__(self, **filters):
self.filters = _process_filters(filters) if filters else {}

def __or__(self, other):
f = F()
if 'or' in self.filters:
f.filters = self.filters
f.filters['or'].append(other.filters)
elif 'or' in other.filters:
f.filters = other.filters
f.filters['or'].append(self.filters)
else:
f.filters = {'or': [self.filters, other.filters]}
return f


class S(object):
def __init__(self, query=None, type=None, **filters):
if query:
Expand All @@ -58,8 +78,15 @@ def __init__(self, query=None, type=None, **filters):
self.objects = []
self.type = type

def filter(self, **filters):
self.filter_ = _process_filters(filters)
def filter(self, f=None, **filters):
"""
Takes either a kwargs of ``and`` filters. Or it takes an ``F`` object.
"""
if f:
self.filter_ = f.filters
else:
self.filter_ = _process_filters(filters)

return self

def facet(self, field, global_=False):
Expand Down
17 changes: 16 additions & 1 deletion tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""
from unittest import TestCase

from elasticutils import S, get_es
from elasticutils import F, S, get_es
from nose.tools import eq_


Expand Down Expand Up @@ -34,6 +34,21 @@ def test_q_all(self):
def test_filter(self):
eq_(len(S(tag='awesome')), 3)

def test_filter_and(self):
eq_(len(S(tag='awesome', foo='bar')), 1)

def test_filter_or(self):
eq_(len(S().filter(F(tag='awesome') | F(tag='boat'))), 4)

def test_filter_or_3(self):
eq_(len(S().filter(F(tag='awesome') | F(tag='boat') |
F(tag='boring'))), 5)
eq_(len(S().filter(F(foo='bar') |
(F(tag='boat') | F(tag='boring')))), 3)

def test_filter_complicated(self):
eq_(len(S().filter(F(tag='awesome', foo='bar') | F(tag='boring'))), 2)

def test_facet(self):
eq_(S().facet('tag').get_facet('tag'),
dict(awesome=3, boring=1, boat=1))
Expand Down

0 comments on commit ccc0a11

Please sign in to comment.