Chain Aggregations like Zappos

44 views
Skip to first unread message

Nikolay Nikolov

unread,
Feb 27, 2016, 5:05:26 AM2/27/16
to Elastica - Elasticsearch PHP Client
Hi folks, I am new here in the group. I need to rebuild my search engine to the new version of Elastica and now I have the problem with chained Aggregations like on the most E-Commerce sites. Here an example tutorial: 


I have this running example with 2 aggregations:


<?php
// Create the actual search query
$elasticaQuery
= new Elastica\Query();

// create the multimatch
$query
= new Elastica\Query\MultiMatch();
$query
->setQuery($queryParam);
$query
->setFields(array('title^12', 'description', 'company_name'));
$query
->setType("cross_fields");
$query
->setOperator("and");

// create bool query object
$elasticaFilterBool
= new Elastica\Query\BoolQuery();


if(!is_null($type_id)){            

       $filter1 = new Elastica\Query\Terms();      

       $filter1->setTerms('job_type_id', $type_id_array);    

        $elasticaFilterBool->addMust($filter1);

}


if(!is_null($location_id)){            

       $filter2 = new Elastica\Query\Terms();      

       $filter2->setTerms('location_id', $location_id_array);  

       $elasticaFilterBool->addMust($filter2);

}


// add the filter to the query Object
$elasticaFilterBool
->addMust($query);


// set up the aggregations
$termsAgg
= new Elastica\Aggregation\Terms("location_id");
$termsAgg
->setField("location_id");
$termsAgg
->setSize(10);
$elasticaQuery
->addAggregation($termsAgg);

$termsAgg1
= new Elastica\Aggregation\Terms("job_type_id");
$termsAgg1
->setField("job_type_id");
$termsAgg1
->setSize(10);
$elasticaQuery
->addAggregation($termsAgg1);


$elasticaQuery
   
->setFrom(0)
   
->setSize(10)
   
->setSort(['find_date' => 'desc']);

$elasticaQuery
->setQuery($elasticaFilterBool);



How to concat the aggregations, so they are chained. If I select one of the filter, the aggregations of this filter should show all num_documents for each value and the other aggregation should change.


Thanks

Nik




Nikolay Nikolov

unread,
Feb 27, 2016, 5:07:06 AM2/27/16
to Elastica - Elasticsearch PHP Client

ruflin

unread,
Feb 27, 2016, 8:38:50 AM2/27/16
to Elastica - Elasticsearch PHP Client
Can you paste here the JSON document with the queries inside you would expect to be created by Elastica? Best is copy them from the blog and adjust them to your need. This makes it easiest to help to transfer them to an Elastica query.

Nikolay Nikolov

unread,
Feb 27, 2016, 10:08:28 AM2/27/16
to Elastica - Elasticsearch PHP Client
I get this JSON from the tutorial I have post. 

{
    "filter": { "and": [ { "terms": { "user": [ "gansbrest", "max" ] } } ] },
    "aggs": { 
        "user": {
            "filter": { "match_all": {} },
            "aggs": {
                "user": {
                    "terms": {
                        "field": "user"
                    }
                }
            }
        },
        "tag": {
            "filter": { "and": [ { "terms": { "user": [ "gansbrest", "max" ] } } ] },
            "aggs": {
                "tag": {
                    "terms": {
                        "field": "tag"
                    }
                }
            }
        }
    }
}'

ruflin

unread,
Feb 28, 2016, 4:45:41 AM2/28/16
to Elastica - Elasticsearch PHP Client
I think what you are looking for is the filter aggregation: https://github.com/ruflin/Elastica/blob/master/lib/Elastica/Aggregation/Filter.php

You should create two filter aggregation and then add you Terms aggregation to the specific filter aggregation. The Filter aggregation must be added to the query. I assume by chained you mean nested? Each aggregation has the addAggregation function: http://elastica.io/api/classes/Elastica.Aggregation.AbstractAggregation.html#method_addAggregation

Nikolay Nikolov

unread,
Feb 28, 2016, 11:11:25 AM2/28/16
to Elastica - Elasticsearch PHP Client
Hi ruflin, are the filters not Deprecated? I am confused.

Is it possible to show me on this example how to make it, because I had small problems with this:

There are 2 filters with 2 aggregations. How to nest it, so when the one filter is set, the other is changes and reverse:

<?php

// Create the actual search query
$elasticaQuery
= new Elastica\Query();

// create the multimatch
$query
= new Elastica\Query\MultiMatch();
$query
->setQuery($queryParam);
$query
->setFields(array('title^12', 'description', 'company_name'));
$query
->setType("cross_fields");
$query
->setOperator("and");

//create bool query object
$elasticaFilterBool
= new Elastica\Query\BoolQuery();

// check for filter $type_id
if(!is_null($type_id)){            
 $filter1
= new Elastica\Query\Terms();
       
 $filter1
->setTerms('job_type_id', $type_id);
 $elasticaFilterBool
->addMust($filter1);
}

// check for filter $location_id
if(!is_null($location_id)){            
 $filter2
= new Elastica\Query\Terms();
       
 $filter2
->setTerms('location_id', array($location_id)); //$location_id is array      
 $elasticaFilterBool
->addMust($filter2);
}

// add the filter to the queryObject
$elasticaFilterBool
->addMust($query);

// set up the aggregation

$termsAgg
= new Elastica\Aggregation\Terms("location_id");
$termsAgg
->setField("location_id");
$termsAgg
->setSize(10);
$elasticaQuery
->addAggregation($termsAgg);
$termsAgg1
= new Elastica\Aggregation\Terms("job_type_id");
$termsAgg1
->setField("job_type_id");
$termsAgg1
->setSize(10);
$elasticaQuery
->addAggregation($termsAgg1);

$elasticaQuery
   
->setFrom(0)
   
->setSize(10);

$elasticaQuery
->setQuery($elasticaFilterBool);



Thanks
Nik

ruflin

unread,
Mar 1, 2016, 4:49:50 AM3/1/16
to Elastica - Elasticsearch PHP Client
About the filters: Yes and No. You can now use any query as filter. See here: https://github.com/ruflin/Elastica/blob/master/lib/Elastica/Aggregation/Filter.php#L23

In your example above it currently still seems, like you just add both aggregations to the query. What I understood is that you want to nest them. This means:

$agg1->addAggregation($agg2);
$query-AddAggregation($agg1);

So in total you need 3 aggregations and not two. But I'm not 100% sure I understood so far what you mean with the filters.

Nikolay Nikolov

unread,
Mar 1, 2016, 11:15:10 AM3/1/16
to Elastica - Elasticsearch PHP Client
Hm I am confused. The aggregations are included in the main query:

$query-AddAggregation($agg1);

what menas, that the aggreagation will aggregate only this rows, which are found by the main query and his filter. For example, if I look for some job in London, the aggregation has not any city, except London which it will aggregate.

But I want, that if I am looking for job in London, I would like to have also aggregated the cities nearby London with this job. Should I understand, that this is only possible with a second query?

ruflin

unread,
Mar 3, 2016, 8:30:06 AM3/3/16
to Elastica - Elasticsearch PHP Client
Was that here what you were looking for? https://groups.google.com/forum/#!topic/elastica-php-client/BlIOX-WN4d0

What you describe sounds like two different queries: One is doing aggregations for all cities inside a specific geo distance. The other one is not an aggregation but a query and returns you all jobs that match in London.
Reply all
Reply to author
Forward
0 new messages