Boolean fields in django-haystack

Say, you're using django-haystack to integrate search & faceting to your project, backed by ElasticSearch. The index that you're building has a boolean field:

class SampleIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True)
    sample_bool = indexes.BooleanField(model_attr='sample_bool')

Then, you try filtering by that boolean field like you'd normally do with a Django's QuerySet:

>>> from haystack.query import SearchQuerySet
>>> SearchQuerySet().count()
42
>>> SearchQuerySet().filter(sample_bool=True).count()
42

Is it really correct? Given that there are only boolean values in existence are True and False, you'd expect filtering on False should give you exactly zero results. Let's verify that:

>>> SearchQuerySet().filter(sample_bool=False).count()
42

wat

Well, that's because when translating a query to language that ElasticSearch understands, both True and False are turned into their stringified representations ("True" and "False") which both evaluate to a truthy value. In fact, any non-empty string would also yield the same result:

>>> SearchQuerySet().filter(sample_bool='example').count()
42

To get the results we expect we need to pass "true" and "false" (lowercase strings):

>>> SearchQuerySet().filter(sample_bool='true').count()
42
>>> SearchQuerySet().filter(sample_bool='false').count()
0

ElasticSearch 5 warns you against passing boolean values directly:

[WARN ][o.e.d.i.m.BooleanFieldMapper] searching using boolean value [False] is deprecated, please use [true] or [false]

And that's what is called a leaky abstraction. In order to query on boolean fields, users need to be aware of how the underlying implementation behaves.