4

I am using elasticsearch-dsl-py and would like to filter on a term that is contained inside another one like this:

"slug": {
    "foo": "foo-slug",
    "bar": "bar-slug "
}

What I do is this :

search.query(‘filtered’, filter={"term": {"slug.foo": "foo-slug"}})

I would prefer something like

search.filter(term, slug.foo="foo-slug")

But I can’t as keyword can’t include dots.

ltbesh
  • 667
  • 1
  • 10
  • 24
  • I am not a Python expert by any stretch, but can't you use the dictionary syntax from the `query`? As in `search.filter(term, {'slug.foo':'foo-slug'})`? – pickypg Nov 20 '14 at 00:46

5 Answers5

11

If it helps anyone else, I had the same problem creating this kind of query against a child property not using nested objects. I found the solution was to use the query method instead of the filter method:

search.query('match', **{"slug.foo": "foo-slug"})

This worked for me in ElasticSearch 1.5.2.

aaronfay
  • 1,673
  • 1
  • 17
  • 19
8

edit... DON'T DO THIS: See aaronfay's answer for the correct approach.

This doesn't seem to be documented anywhere which is sad...

>>> search.filter('term', slug__foo='foo-slug').to_dict()
{'query': {'filtered': {'filter': {'term': {u'slug.foo': 'foo-slug'}}, 'query': {'match_all': {}}}}}

The double underscore will be converted into dot notation. No idea if this is stable.

Charles
  • 1,820
  • 13
  • 16
0

So I am assuming that slug is a nested object in a larger document. In the current version (0.0.8) this can be achieved like so:

from elasticsearch_dsl import F

...

f = F('term', foo='foo-slug')
search = search.filter('nested', path='slug', filter=f)
aamiri
  • 2,420
  • 4
  • 38
  • 58
0

It's a long time after the question had been asked, but just in case anyone comes across this post, Charles's answer is actually correct, (The method shouldn't break since it's actually mentioned in the packages docs now).

As the docs mention:

...,the Q shortcut (as well as the query, filter, and exclude methods on Search class) allows you to use __ (double underscore) in place of a dot in a keyword argument:

s = Search()
s = s.filter('term', category__keyword='Python')
s = s.query('match', address__city='prague')

It also mentions aaronfay's answer:

Alternatively you can always fall back to python’s kwarg unpacking if you prefer:

s = Search()
s = s.filter('term', **{'category.keyword': 'Python'})
s = s.query('match', **{'address.city': 'prague'})
Bahman Rouhani
  • 1,139
  • 2
  • 14
  • 33
-2

This will do the trick for you:

args = {
    "slug.foo": "foo-slug"
}
search.filter(term, **args)