rs82uk
rs82uk

Reputation: 739

Elastic NEST Filter on Aggregations

Ive now successfully got my c# Test win forms app working with aggregations and now I want to be able to filter on said aggregations if someone selects one (or more) of them.

Here is my query that is working exactly as I want and I am getting both price range buckets and buckets for each of the specification terms that it can find in the index.

.Aggregations(a => a
            .Nested("specifications", n => n
                .Path(p => p.ProductSpecification)
                .Aggregations(aa => aa.Terms("groups", sp => sp.Field(p => p.ProductSpecification.Suffix("name"))
                    .Aggregations(aaa => aaa
                        .Terms("attribute", tt => tt.Field(ff => ff.ProductSpecification.Suffix("value"))))
                        )
                        )
                    )
            .Range("price_range", ra => ra
                .Field(p => p.Price)
                .Ranges(
                    r => r.To(50),
                    r => r.From(50).To(100),
                    r => r.From(100).To(150),
                    r => r.From(150).To(200),
                    r => r.From(200).To(250),
                    r => r.From(250)
                    )
                ))
        .Index("myindex")
        .Type("product")
        .Query(q => q
            .MultiMatch(m => m
                .Query(searchBox.Text + "*")
                .Fields(ff => ff
                    .Field(f => f.Name, boost: nameBoost)
                    .Field(f => f.Description, boost: descriptionBoost)
                    .Field(f => f.ProductCode)))));

Can someone point me in the direction of how I can go about filtering down results based on selecting any of these buckets.

UPDATE (30/01/18) I have now added this to my query

&& q.Nested(n => n
            .Path(p => p.ProductSpecification)
            .Query(q2 => q2
                .Terms(t => t
                    .Field(f => f.ProductSpecification.Suffix("name"))
                    .Terms("Guarantee",)
                    )).Query(q3 => q3
                        .Terms(t2 => t2
                            .Field(f2 => f2.ProductSpecification.Suffix("value"))
                            .Terms("3 years","10 years")
                            )))

                    ));

This is enabling me to pass multiple values into one Spec filter, but what im not sure on how to achieve is how to filter on multiple specs so the above filters on Guarantee with values of either 3 or 10 years but if I also wanted to pass values of "Grey" and "Copper" to the spec of "Colour"

Adding "Colour" into My first set of terms and "Grey" and "Copper" into my second terms list breaks all filtering. I think im close here just need a little direction

Upvotes: 2

Views: 723

Answers (1)

Russ Cam
Russ Cam

Reputation: 125488

If I understand your question correctly, when the user selects a price range from the price range facets that are applicable to the query that is being executed, you'd like to apply this price range to the query?

The Post Filter serves this purpose, by applying a filter to the search results after aggregations have been calculated.

Assuming a user has selected the 50-100 price range, your query would like something like

var response = client.Search<Product>(s => s
    .Aggregations(a => a
        .Nested("specifications", n => n
            .Path(p => p.ProductSpecification)
            .Aggregations(aa => aa
                .Terms("groups", sp => sp
                    .Field(p => p.ProductSpecification.Suffix("name"))
                    .Aggregations(aaa => aaa
                        .Terms("attribute", tt => tt
                            .Field(ff => ff.ProductSpecification.Suffix("value"))
                        )
                    )
                )
            )
        )
        .Range("price_range", ra => ra
            .Field(p => p.Price)
            .Ranges(
                r => r.To(50),
                r => r.From(50).To(100),
                r => r.From(100).To(150),
                r => r.From(150).To(200),
                r => r.From(200).To(250),
                r => r.From(250)
            )
        )
    )
    .Index("myindex")
    .Type("product")
    .Query(q => q
        .MultiMatch(m => m
            .Query(searchBox.Text + "*")
            .Fields(ff => ff
                .Field(f => f.Name, boost: nameBoost)
                .Field(f => f.Description, boost: descriptionBoost)
                .Field(f => f.ProductCode)
            )
        )
    )
    .PostFilter(pf => pf
        .Range(r => r
            .Field(f => f.Price)
            .GreaterThanOrEquals(50)
            .LessThan(100)
        )
    )
);

Upvotes: 3

Related Questions