summaryrefslogtreecommitdiff
path: root/docs/reference/search/request/post-filter.asciidoc
blob: 489ea96c842906d45847861665806a373b5788b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
[[search-request-post-filter]]
=== Post filter

The `post_filter` allows any filter that it holds to be executed as last filter, because
of this the `post_filter` only has affect on the search hits and not facets.

There are several reasons why to specify filters as `post_filter`. One reason is to force
expensive filters to be executed as last filter, so that these filters only operate on the
docs that match with the rest of the query. An example of for what filter a post_filter
should be used for this reason is the `geo_distance` filter. The `geo_distance` filter is
in general an expensive filter to execute and to reduce the execution time for this filter,
one can choose to specify it as `post_filter`, so it runs on documents that are very likely
to be end up as matching documents.

Another important reason is when doing things like facet navigation,
sometimes only the hits are needed to be filtered by the chosen facet,
and all the facets should continue to be calculated based on the original query.
The `post_filter` element within the search request can be used to accomplish it.

Note, this is different compared to creating a `filtered` query with the
filter, since this will cause the facets to only process the filtered
results.

For example, let's create two tweets, with two different tags:

[source,js]
--------------------------------------------------
curl -XPUT 'localhost:9200/twitter/tweet/1' -d '
{
    "message" : "something blue",
    "tag" : "blue"
}
'

curl -XPUT 'localhost:9200/twitter/tweet/2' -d '
{
    "message" : "something green",
    "tag" : "green"
}
'

curl -XPOST 'localhost:9200/_refresh'
--------------------------------------------------

We can now search for something, and have a terms facet.

[source,js]
--------------------------------------------------
curl -XPOST 'localhost:9200/twitter/_search?pretty=true' -d '
{
    "query" : {
        "term" : { "message" : "something" }
    },
    "facets" : {
        "tag" : {
            "terms" : { "field" : "tag" }
        }
    }
}
'
--------------------------------------------------

We get two hits, and the relevant facets with a count of 1 for both
`green` and `blue`. Now, let's say the `green` facet is chosen, we can
simply add a filter for it:

[source,js]
--------------------------------------------------
curl -XPOST 'localhost:9200/twitter/_search?pretty=true' -d '
{
    "query" : {
        "term" : { "message" : "something" }
    },
    "post_filter" : {
        "term" : { "tag" : "green" }
    },
    "facets" : {
        "tag" : {
            "terms" : { "field" : "tag" }
        }
    }
}
'
--------------------------------------------------

And now, we get only 1 hit back, but the facets remain the same.

Note, if additional filters are required on specific facets, they can be
added as a `facet_filter` to the relevant facets.