Use Drupal Views Group By Module to Show Closest Matches by Terms

Someone requested that I add functionality to my Drupal featured content block module to sort by the nodes that are the closest match to the node being viewed based on vocabulary terms. I did this, but then someone asked if I could integrate with views to allow for this same type of sorting. I thought maybe it could be done already, and sure enough, I was able to do it using views and the views group by module.

Make sure you are using a recent version of views (e.g. 6.x-2.8) and have installed & enabled the Views Group By module.

I've exported my view so you can play with it:

$view = new view;
$view->name = 'closest_match_by_terms';
$view->description = '';
$view->tag = '';
$view->view_php = '';
$view->base_table = 'node';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->override_option('fields', array(
  'nid' => array(
    'label' => 'Nid',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 0,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 0,
    'exclude' => 0,
    'id' => 'nid',
    'table' => 'node',
    'field' => 'nid',
    'relationship' => 'none',
  ),
  'title' => array(
    'label' => 'Title',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 0,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 1,
    'exclude' => 0,
    'id' => 'title',
    'table' => 'node',
    'field' => 'title',
    'relationship' => 'none',
  ),
  'tid' => array(
    'label' => 'Term ID Count',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 0,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'set_precision' => FALSE,
    'precision' => 0,
    'decimal' => '.',
    'separator' => ',',
    'prefix' => '',
    'suffix' => '',
    'exclude' => 0,
    'id' => 'tid',
    'table' => 'term_data',
    'field' => 'tid',
    'override' => array(
      'button' => 'Override',
    ),
    'relationship' => 'none',
  ),
  'views_sql_groupedfields' => array(
    'label' => 'Group By Fields',
    'alter' => array(
      'alter_text' => FALSE,
      'text' => '',
      'make_link' => FALSE,
      'path' => '',
      'alt' => '',
      'link_class' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'trim' => FALSE,
      'max_length' => '',
      'word_boundary' => TRUE,
      'ellipsis' => TRUE,
      'strip_tags' => FALSE,
      'html' => FALSE,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => '1',
    'id' => 'views_sql_groupedfields',
    'table' => 'views_groupby',
    'field' => 'views_sql_groupedfields',
    'relationship' => 'none',
    'views_groupby_fields_to_group' => array(
      'nid' => 'nid',
    ),
    'views_groupby_sql_function' => 'count',
    'views_groupby_fields_to_aggregate' => array(
      'tid' => 'tid',
    ),
    'views_groupby_field_sortby' => 'tid',
    'views_groupby_sortby_direction' => 'desc',
    'override' => array(
      'button' => 'Override',
    ),
  ),
));
$handler->override_option('arguments', array(
  'tid' => array(
    'default_action' => 'default',
    'style_plugin' => 'default_summary',
    'style_options' => array(),
    'wildcard' => 'all',
    'wildcard_substitution' => 'All',
    'title' => '',
    'breadcrumb' => '',
    'default_argument_type' => 'php',
    'default_argument' => '',
    'validate_type' => 'none',
    'validate_fail' => 'not found',
    'break_phrase' => 1,
    'add_table' => 1,
    'require_value' => 0,
    'reduce_duplicates' => 0,
    'set_breadcrumb' => 0,
    'id' => 'tid',
    'table' => 'term_node',
    'field' => 'tid',
    'validate_user_argument_type' => 'uid',
    'validate_user_roles' => array(
      '2' => 0,
    ),
    'override' => array(
      'button' => 'Override',
    ),
    'relationship' => 'none',
    'default_options_div_prefix' => '',
    'default_argument_user' => 0,
    'default_argument_fixed' => '',
    'default_argument_php' => 'if (arg(0) == \'node\' && is_numeric(arg(1))) {
  $node = node_load(arg(1));
  if ($node->nid) {
    $terms = $node->taxonomy;
    if (! empty($terms)) {
      $tids = array();
      foreach ($terms as $term_data) {
         $tids[] = $term_data->tid;
      }
      return implode(\'+\', $tids);
    }
  }
}
 ',
    'validate_argument_node_type' => array(
      'webform' => 0,
      'forum' => 0,
      'page' => 0,
      'story' => 0,
    ),
    'validate_argument_node_access' => 0,
    'validate_argument_nid_type' => 'nid',
    'validate_argument_vocabulary' => array(
      '1' => 0,
      '3' => 0,
      '2' => 0,
    ),
    'validate_argument_type' => 'tid',
    'validate_argument_transform' => 0,
    'validate_user_restrict_roles' => 0,
    'validate_argument_php' => '',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('distinct', 1);
$handler->override_option('style_plugin', 'table');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'asc',
  'columns' => array(
    'nid' => 'nid',
    'name_1' => 'name_1',
    'title' => 'title',
    'views_sql_groupedfields' => 'views_sql_groupedfields',
  ),
  'info' => array(
    'nid' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'name_1' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'title' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'views_sql_groupedfields' => array(
      'separator' => '',
    ),
  ),
  'default' => '-1',
));
$handler = $view->new_display('block', 'Block', 'block_1');
$handler->override_option('block_description', '');
$handler->override_option('block_caching', -1);

Have fun!

Comments

Thanks!

Thanks Kristen! i'm using this on the story node types at http://www.gatortailgating.com (with a little bit of tweaking the output). I really have been looking for a solution similar to this (that uses views) for a while.. this is perfect.

Thanks again!

Cool

Glad it's working for you. Nice looking site!

Kristen

my Foreclosure page has a problem with follows on sorting items

My Foreclosure page has a problem with follows on sorting items, the idea is that it's giving a lot parameters like :
foreclosures/Michigan?order=field_foreclosure_city_value&sort=asc
and this is no good for SEO, so I' looking for a patch or the lines ofc code in the module where I can add nofollow to these links, do you have any idea where it could be?

Sorting

Is the sorting done with a form or with links? If it's a form, then you don't need to worry about it because the browser won't "use the form". If it's links, then you could right some jQuery that adds on "nofollow" to the links.

I'm not sure there is a module that will selective change certain links with query strings on the page to use nofollow. You could try out the Nofollow List module for that since it *may* do it:

https://www.drupal.org/project/nofollowlist

but then you'd have to specify each of the URLs with all query string parameters.

Good luck,
Kristen

Hello, I have this error: #

Hello,
I have this error:

# Field handler views_groupby.views_sql_groupedfields is not available.
# Field handler views_groupby.views_sql_groupedfields is not available.

Latest Views

If you update to the latest views, that error should go away.

Kristen

I have 6.x-2.8 do you mean

I have 6.x-2.8
do you mean 6.x-3.0-alpha2?

6.x-2.8

I'm using 6.x-2.8 as well. When I had used an earlier version, I got that error.

Hmmm... you could try:

* running update.php
* clearing all your caches

Kristen

Views Group By Module

Do you have the Views Group By module installed? You need that for this view code to work.

Kristen

Thank You for this - works with views 2 & 3

Thank You for this sweet piece of code. I have been looking for something like this for a while & also cannot believe that this works with both views 2 & views 3. Great job.

To not display the current node you are on in the view (since this is for related nodes& therefore it should not include the actual node itself) - add a new argument - node:nid - default argument: node id from url - exclude this

Cool!

Glad to hear it's working in views 3, and thanks for the extra tip for excluding the currently viewed node.

Kristen

I've been waiting a year to

I've been waiting a year to see it...

Thank you! :]

I'm a Speaker at DrupalCon Portland