Skip to content

Commit eb4a302

Browse files
committed
Add percolator example and improvements
Fixes elastic#861
1 parent 15b2b94 commit eb4a302

File tree

6 files changed

+95
-2
lines changed

6 files changed

+95
-2
lines changed

Changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ directory. Documentation has been updated to reflect the new API.
2525
``7.x``. It does, however, work in the new way which is not fully backwards
2626
compatible.
2727

28+
* ``Percolator`` field now expects ``Query`` objects as values
2829
* you can no longer access meta fields on a ``Document`` instance by specifying
2930
``._id`` or similar. Instead all access needs to happen via the ``.meta``
3031
attribute.

elasticsearch_dsl/field.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
from datetime import date, datetime
77

88
from dateutil import parser, tz
9-
from six import itervalues, string_types, iteritems
9+
from six import string_types, iteritems
1010
from six.moves import map
1111

12-
from .utils import DslBase, ObjectBase, AttrDict, AttrList
12+
from .query import Q
13+
from .utils import DslBase, AttrDict, AttrList
1314
from .exceptions import ValidationException
1415

1516
unicode = type(u'')
@@ -357,6 +358,15 @@ class Completion(Field):
357358

358359
class Percolator(Field):
359360
name = 'percolator'
361+
_coerce = True
362+
363+
def _deserialize(self, data):
364+
return Q(data)
365+
366+
def _serialize(self, data):
367+
if data is None:
368+
return None
369+
return data.to_dict()
360370

361371
class IntegerRange(Field):
362372
name = 'integer_range'

examples/README.rst

+6
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ A helper function using the `composite aggregation
2828
<https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-composite-aggregation.html>`_
2929
to paginate over aggregation results.
3030

31+
``percolate.py``
32+
----------------
33+
34+
A ``BlogPost`` document with automatic classification using the `percolator
35+
<https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-percolate-query.html>`_
36+
functionality.

examples/percolate.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from elasticsearch_dsl import Document, Percolator, Text, Keyword, \
2+
connections, Q, Search
3+
4+
connections.create_connection()
5+
6+
class BlogPost(Document):
7+
"""
8+
Blog posts that will be automatically tagged based on percolation queries.
9+
"""
10+
content = Text()
11+
tags = Keyword(multi=True)
12+
13+
class Index:
14+
name = 'test-blogpost'
15+
16+
def add_tags(self):
17+
# run a percolation to automatically tag the blog post.
18+
s = Search(index='test-percolator')
19+
s = s.query('percolate',
20+
field='query',
21+
index=self._get_index(),
22+
document=self.to_dict())
23+
24+
# collect all the tags from matched percolators
25+
for percolator in s:
26+
self.tags.extend(percolator.tags)
27+
28+
# make sure tags are unique
29+
self.tags = list(set(self.tags))
30+
31+
def save(self, **kwargs):
32+
self.add_tags()
33+
return super(BlogPost, self).save(**kwargs)
34+
35+
class PercolatorDoc(Document):
36+
"""
37+
Document class used for storing the percolation queries.
38+
"""
39+
# relevant fields from BlogPost must be also present here for the queries
40+
# to be able to use them. Another option would be to use document
41+
# inheritance but save() would have to be reset to normal behavior.
42+
content = Text()
43+
44+
# the percolator query to be run against the doc
45+
query = Percolator()
46+
# list of tags to append to a document
47+
tags = Keyword(multi=True)
48+
49+
class Index:
50+
name = 'test-percolator'
51+
52+
def setup():
53+
# create the percolator index if it doesn't exist
54+
if not PercolatorDoc._index.exists():
55+
PercolatorDoc.init()
56+
57+
# register a percolation query looking for documents about python
58+
PercolatorDoc(
59+
_id='python',
60+
tags=['programming', 'development', 'python'],
61+
query=Q('match', content='python')
62+
).save(refresh=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../examples/percolate.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from .percolate import setup, BlogPost
2+
3+
def test_post_gets_tagged_automatically(write_client):
4+
setup()
5+
6+
bp = BlogPost(_id=47, content='nothing about snakes here!')
7+
bp_py = BlogPost(_id=42, content='something about Python here!')
8+
9+
bp.save()
10+
bp_py.save()
11+
12+
assert [] == bp.tags
13+
assert set(('programming', 'development', 'python')) == set(bp_py.tags)

0 commit comments

Comments
 (0)