Entity view (Content)

Drupal Project Spotlight – J.D. Power Advanced Search

By smulvihill
Sep. 7, 2017

Appnovation was recently tasked to redesign J.D. Power’s car and article search functionality. The current car search implementation was based on Drupal views searching against the database, while the article search was a basic Apachesolr (Drupal contrib module) search page. The car and article search functionality was to be based on Apache Solr and allow for full-text and faceted search.

MULHIVILL BLOG 1.png

 

During the discovery phase of the project we realized that there were five fields missing from the model content type that were needed for faceting. The data for these fields was available in custom database tables, populated by the Chrome Data API, but would need to be migrated into the content type to allow Apachesolr to re-index nodes when these values change. Data mapping files were also required to ensure the migrated data fields could be categorized and added as taxonomy terms.

During the development of the car and article facets, there were some unique challenges that presented themselves:

-The ‘Year’ facet was only to show eight items, with the eighth item being ‘[year] or Earlier’. For example, if 2018 cars are the most recent, then the last facet item should show results for 2011 or earlier. To achieve this, we needed to programmatically build a custom facet item that would aggregate all items less than or equal to 2011. First we needed to loop through all facet items to get the total result count for all facet items 2011 or earlier.

To ensure the proper values were being returned from Solr when the facet item was selected, a range query was used. Then we needed to build some logic around detecting when the facet item was active or inactive so that when it was selected we could make its’ checkbox active. At the end of this article there is a helper function that we used to get all active facet items to help us accomplish this task.

MULHIVILL BLOG 2.png

-The ‘Ratings & Awards’ facet was to have four items, each one its’ own field on the model content type. One of these fields was a Boolean field, so we decided to base the ‘Ratings & Awards’ facet off of this field’s facet as it then only meant adding custom facet items and not removing anything.

For the other three fields, we enabled their facets in facetapi so we could access their data. We programmatically loaded the other three facets to get their build info, which we used to create the three custom facet items. Find a helper function below that we used return facet build information from a faceted field.

Mulhivill Blog 3.png

One of the most difficult aspects of this project was actually removing existing functionality. Since there was already a site-wide search built on Apachesolr, it was important to keep this intact while removing any remnants of the existing car and article search to keep the codebase as clean as possible.

Overall this project was a success and is now available in the production environment, take a look:

http://www.jdpower.com/cars/search

http://www.jdpower.com/cars/article/search

We created some useful helper functions to accomplish the tasks listed in this article. I will provide them here for others to use.

/**

 * Helper function to return all active facet items

 */

function _appnovation_get_active_facet_items() {

            $adapter = facetapi_adapter_load(APPNO_SOLR_SEARCHER);

            $active_items = $adapter->getAllActiveItems();

            return $active_items;

}

/**

 * Helper function to return facet build info for a field

 */

function _appnovation_get_facet_items_from_facet($field) {

            $adapter = facetapi_adapter_load(APPNO_SOLR_SEARCHER);

            $realm = facetapi_realm_load('block');

            $facet = new FacetapiFacet($adapter, facetapi_facet_load($field, APPNO_SOLR_SEARCHER));

            $processor = new FacetapiFacetProcessor($facet);

            $processor->process();

            $facet->build($realm, $processor);

            $build_list = $facet->getBuild();

            return $build_list;

}