1. Introduction

1.1 Background

A list of distinct active taxonomy terms can be useful as it allows visitors to browse content by taxonomy term (categories). Trying to set up such a list using views often results in a list with duplicates. As lots of people seem to hit the same wall when trying to set this up I thought I'd put in the effort of creating this recipe. :)

1.2 Requirements

For this you'll need to have views installed and taxonomy enabled. You should already know how to set up vocabularies and how to categorize content. If not, you may want to read the Taxonomy handbook first.

1.3 Update history

When I first created this recipe I used a method provided by Himerus on his website. After a couple of months a much, much easier way of doing this became available thanks to joel_guesclin and merlinofchaos.

2. Solutions

2.1 Solution using Term View

This solution is easier than the original (advanced solution) recipe found below while still offering the required flexibility to group terms etc. It uses Term View and not Node View thus preventing the duplicates issue.

1) add a new view of view type "term" (not the default "node" option!) by ticking the correct option after clicking 'add view'
2) add the Taxonomy Term to the list of Fields
3) Add a relationship "Taxonomy: Node" and make it obligatory
4) In the basic settings enable the 'distinct' option.
5) Add some filters to narrow the results as needed. (i.e. only nodes from a certain content type)

That's it! This should solve the enormous amount of issues with duplicates. :)

2.2 Original recipe

Below is the original, more difficult and probably less efficient recipe. I kept this for archiving purposes. Maybe it is still useful to some although I do recommend the method described above.

2.2.1 Basic setup

Regardless of whether you go for the basic or advanced solution, make sure you have done the following:

1) add a new view of view type "node"
2) set row style to "Fields"
3) optionally set style to "Grid"
4) though not strictly necessary lots of you will want to add filters to limit the content types and limit to published content.
5) add a field "Taxonomy: Term"

Now, usually the resulting list contains duplicates as the view simply lists the terms of every node that passes the filtercriteria. So if there are two nodes that pass the filter and both have taxonomy term "little green birds", the list would contain two instances of "little green birds".

There's a basic solution and a more advanced solution:

2.2.2 Basic solution

The basic solution, thanks to drupal3008 uses the views "Arguments" section:
1) add an argument for "Taxonomy: Term"
2) Title: %1
3) Action to take: Summary, sorted Ascending
4) Wildcard: All
5) Wildcard Title: All
6) Basic Validation
7) Hide view / Page...
8) Case: Capitalize each word (This is my preference)
9) Case in path: Lower case
10) Transform spaces to dashes (checked)
11) On next option after you add field, select: List

This presents you with a basic list of all active taxonomy terms. However, it strips the possibility to order the terms according to vocabulary and allows little control over the output.

2.2.3 Advanced solution

The advanced solution involves creating a custom module for using hook_views_pre_render:

custom.info

; $Id:

name = "Custom"
description = "This module contains modifications to modules so that the modules themselves can be easily upgraded without redoing the modifications."
package = "Administration"
core = 6.x

custom.module, copied from himerus' website

<?php
// $Id$

/**
 * Implementation of hook_views_pre_render
 * This function is in place to filter out duplicate taxonomy terms
 * From listings. It will cycle each result, and store a new array of
 * unique terms, and when a duplicate is found, will unset that result
 *
 * @param $view
 */
function your_module_views_pre_render($view){
 // first we make sure we are dealing with the correct view
 if ($view->name == "your_view_name") {
  // create our array for comparisons
  $unique_tids = array();
  // let's cycle through each default result, and do some dirty stuff
  foreach($view->result AS $k => $result){
   if(in_array($result->node_node_data_YOUR_FIELD__term_data_tid, $unique_tids) || !$result->node_node_data_YOUR_FIELD__term_data_tid) {
    /* we already have seen this TID in the results, so blow that crap away
     * also will blow away any that are empty for some odd reason 
     */
    unset($view->result[$k]);
   }
   else {
    // this is a term we haven't seen, so let's not blow it away, but add
    // it to our array of unique id's to present as the "true" result of this view
    $unique_tids[$k] = $result->node_node_data_YOUR_FIELD__term_data_tid;
   }
  }
  /* now, we have an accurate unique list of terms in $unique_tids
   * next, we cycle those to reorder the crap random ordering
   * since these tids were pulled from the nodes in the order they were
   * set to sort from the node type view 
   */
  $alpha_arr = array();
  // cycle each of our unique tids, referencing the original key of the view->result array ($k)
  foreach($unique_tids AS $k => $tid) {
   // we need to grab the term now, not the tid to sort alpha
   $alpha_arr[$k] = strtolower($view->result[$k]->node_node_data_YOUR_FIELD__term_data_name);
  }
  // sort the array, maintaining the $k key so that we may again reference back to the original data
  asort($alpha_arr);
  // create new array of results to overwrite the current one
  $new_results = array();
  /* cycle one last time now that we have unique terms, sorted alphabetically
   *    the point of this is to now take our $k reference, and grab the original $view->result data
   *    that references this item 
   */
  foreach($alpha_arr AS $v => $term_name) {
   $new_results[] = $view->result[$v];
  }
  // get rid of the original result set
  unset($view->result);
  // replace it with our new, accurate result set
  $view->result = $new_results;
 }
}
?>

1) ... remember to delete the PHP closure tag (get rid of ?>) to comply with Drupal coding standards. It's just used here to enable syntax highlighting.
2) replace"your_view_name" in line 14 to, well, your view name.
3) replace YOUR_FIELD with your field. This can be found by hovering over the field "Taxonomy: Term" we just added and looking at the url which appears in the browsers statusbar. The field name is behind the last slash ("/"). Make sure to keep the double underscore after YOUR_FIELD. It's not a typo.
4) enable the module.

Now, this code may or may not not work straight away. If it doesn't it probably has to do with the naming pattern (i.e. "node_node_data_YOUR_FIELD__term_data_name" and "node_node_data_YOUR_FIELD__term_data_tid" should be different)

To find out what the correct naming pattern is insert this just before line 14:

 drupal_set_message('<pre>'. print_r($view, TRUE)  .'</pre>');

Run the live preview of the view (On the edit view form) after which there should be a drupal message showing the contents of array $view.

Look for something like:

[0] => stdClass Object
 (
  [nid] => 249
  [term_data_tid] => 
  [term_data_name] => 
 )

As you can see, in this case "node_node_data_YOUR_FIELD__term_data_name" has to be replaced with "term_data_name" and "node_node_data_YOUR_FIELD__term_data_tid" has to be replaced with "term_data_tid". This is just an example, but should get you going.

Save the lot and you should have a list of distinct, active taxonomy terms. If so, you can start editing the view to your heart's content. This is really the biggest advantage of the more advanced solution. For example, you could group the list by vocabulary if you are using more than one:

1) add a field "Taxonomy: Vocabulary Name"
2) Edit the field to exclude the field from display as we don't want to display this field, we just want to use the data.
3) optionally, rewrite the output of the field to something like: "Browse by [FIELD]", changing FIELD to the fieldname. You can find the fieldname by hovering over the Taxonomy: Vocabulary name" field. Usually it's "name_1".
4) Edit the settings of the view "Style" (click on the cog behind "Style").
4) select Grouping field: "Taxonomy: Vocabulary name"

Comments

UNarmed’s picture

I tried this to the letter and it just didnt do the trick for me =/ When ever i enter

drupal_set_message('

'. print_r($view, TRUE)  .'

'); at line 14 nothing happends either?

I have been struggeling with this views duplicate thing for ages now so help would be greatly appreciated.

RedTop’s picture

... but I'll need more information than that. :)

What did you do to debug this?
Just to make sure:
- did you create a custom module?
- did you change your view name?
- did you change the field names?

My best guess is that your code doesn't use the correct fieldnames (which is what happened to me as well. Took quite a bit of debugging and help). Make sure you use the exact code I posted above:

drupal_set_message('<pre>'. print_r($view, TRUE) .'</pre>');

(I tried again before posting this reply to check that it works).

Enter it on the line after:

if ($view->name == "your_view_name") {

Attach your code in a file if it still doesn't work. :)

UNarmed’s picture

Hey thanks il give this a try. I ended up just creating a term view that displays all my terms irrespective of whether or not they contain content which is not idea but at least i dont get duplicate items anymore. I am going to give your suggestions a try asap because i honestly dont think my way of doing it is close to ideal haha. Thanks for the help =]

Elsiena’s picture

Hello,

This solution worked for me and it doesn't need any coding in PHP.

Add taxonomy term as a filter
Select: is one of and select all the options.
check: Reduce duplicates

chrishrtmn’s picture

Looked everywhere for 2 days for a solution to this same/similar issue I was having and came across this. Worked perfectly, thanks!

testertesters’s picture

Thanks a lot for this – I tried the "easy" version and it worked great. I wonder if anyone knows what the fastest solution is? I suspect the "advanced" solution could get slow from all that looping and calls to in_array, whereas the simple one narrows it down to one database call.. However, this call has "DISTINCT" in it, which I think is bad for performance?

ron_sparks’s picture

This is great I have been coding all day just finished figuring out zip code proximity search and this made browse by taxonomy soooo much easier!
I have a lost... now I'll figure out what to do with my list :)

manoz_79’s picture

Hi,

I used the basic solution and created the list using views as instructed, I am able to display the taxonomy terms with the node count but the links to their taxonomy pages are broken, what could i have done to cause this.

Please help.

Thanks,
Manoj

Diegen’s picture

Same here.. I get a page which says January 1970..

The links of the terms are : blog/term

and the terms attached to the nodes read : category/category/term

so somethings a bit off ?

artik’s picture

THANK YOU!!
I tried two days to found solutions about duplicates in taxonomy terms and... this is it!
THANK YOU A LOT!!!

joel_guesclin’s picture

Unless I've misunderstood, this is exactly what I was trying to do. In fact I wanted to have a block showing tags from a particular vocabulary, with nodes attached that were created during the last 2 months. And indeed I had duplicates in the terms because the DISTINCT was applied to nodes not terms.
The explanation (when it was explained to me) is very simple: DISTINCT is applied depending on query type, so the mistake I was making was to have a Node View. Here is what I did:
1) Create a new Term View (not a Node View like I had before and like the example here)
2) Add the Taxonomy Term to the list of Fields
3) Add a relationship "Taxonomy: Node" and make it obligatory
4) Now the Filters allow me to filter on Node Post Date ("now -2 months")
5) Add another filter to get just the one vocabulary that I want
Hey presto! It works! Thank you Merlin!

RedTop’s picture

That's fantastic! I tried and it works beautifully... I will update this recipe asap. :)

polishyourimage’s picture

Joel, this was easy and worked. thanks.

caponey’s picture

good recipe.
is there a way to display the number of nodes that are in that particular term?
like Term 1 (3), Term 2 (1) Term 3 (0), etc...

banoodle’s picture

If I use the simple solution, it works great but lacks the node counts next to each term. I really need these counts to display.

If I use the 2nd solution, I get the list to display the way I like (with counts), but the links are broken (they direct to the home page). I must be doing something wrong as a lot of people seem happy with this solution. I *think* I'm following the recipe to the letter.

Surely there is a way to have the list with counts and functional links (without having to write PHP) - no?!

I'm on Drupal 6 - maybe that's my problem?

yosisays’s picture

I tried your "easier" idea however when I tested it to see if it points to the correct page I found that it is directing me to sitename.com/term instead of sitename.com/taxonomy/term/$tid . how do i fix this?

alb’s picture

I cannot found a solution;
which is the php code for to hide a field's view?

I read that perhaps the hook is hook_views_pre_render,
but I only found code for hide rows;

any idea for hide fields?

mkoistinen’s picture

Great post. Solve the problem perfectly. A big thanks to RedTop for the post here and Jake Strawn (aka: himerus) for the original solution.

For my application, I needed to retain the weight of the nodes as set by the administrator and thought I'd share that in case someone else was faced with the same requirement.

To use weighted ordering rather than alphabetic ordering, simply replace these lines:

  ...
  foreach($unique_tids AS $k => $tid) {
   // we need to grab the term now, not the tid to sort alpha
   $alpha_arr[$k] = strtolower($view->result[$k]->node_node_data_YOUR_FIELD__term_data_name);
  }
  // sort the array, maintaining the $k key so that we may again reference back to the original data
  asort($alpha_arr);
  ...

with:

  ...
  foreach($unique_tids AS $k => $tid) {
    // Fetch the term so we can access its weight
    $term = taxonomy_get_term($tid);
    // Use the weight as the array index
    $alpha_arr[$term->weight] = strtolower($view->result[$k]->node_node_data_YOUR_FIELD__term_data_name);
  }
  ...

and change the final foreach() loop to:

  ...
  foreach($alpha_arr AS $v => $term_name) {
    $result = $view->result[$v];
    if ($result->term_data_tid) {
      $new_results[] = $result;
    }
  }
  ...

Optionally change the variable name $alpha_arr with $weighted_arr throughout. =)

Ale.bcn’s picture

Hi mkoistinen,

it didn't work for me, Parse error: syntax error, unexpected $end in /var/www/sites/all/modules/custom/custom.module on line 58

// $Id$

/**
* Implementation of hook_views_pre_render
* This function is in place to filter out duplicate taxonomy terms
* From listings. It will cycle each result, and store a new array of
* unique terms, and when a duplicate is found, will unset that result
*
* @param $view
*/
function your_module_views_pre_render($view){
// first we make sure we are dealing with the correct view
if ($view->name == "events_views_taxonomy") {
  // create our array for comparisons
  $unique_tids = array();
  // let's cycle through each default result, and do some dirty stuff
  foreach($view->result AS $k => $result){
   if(in_array($result->node_node_data_name__term_data_tid, $unique_tids) || !$result->node_node$
    /* we already have seen this TID in the results, so blow that crap away
     * also will blow away any that are empty for some odd reason
     */
    unset($view->result[$k]);
   }
   else {
    // this is a term we haven't seen, so let's not blow it away, but add
    // it to our array of unique id's to present as the "true" result of this view
    $unique_tids[$k] = $result->node_node_data_name__term_data_tid;
   }
  }
  /* now, we have an accurate unique list of terms in $unique_tids
   * next, we cycle those to reorder the crap random ordering
   * since these tids were pulled from the nodes in the order they were
   * set to sort from the node type view
   */
  $alpha_arr = array();
  // cycle each of our unique tids, referencing the original key of the view->result array ($k)

   foreach($unique_tids AS $k => $tid) {
    // Fetch the term so we can access its weight
    $term = taxonomy_get_term($tid);
    // Use the weight as the array index
    $alpha_arr[$term->weight] = strtolower($view->result[$k]->node_node_data_name__term_data_nam$
  }

  // create new array of results to overwrite the current one
  $new_results = array();
  /* cycle one last time now that we have unique terms, sorted alphabetically
   *    the point of this is to now take our $k reference, and grab the original $view->result d$
   *    that references this item
   */
  foreach($alpha_arr AS $v => $term_name) {

    $result = $view->result[$v];
    if ($result->term_data_tid) {
    $new_results[] = $result;
}
}

Help please!

tnx

gmoreno’s picture

You are missing a closing "}"

henkit’s picture

Hi,

I was also struggeling with creating a distinct view of active taxonomy terms, needed it in combination with taxonomy image and only needed to see the first 8....maybe it's a stupid suggestion but what i did was the following:

1. Created a content type corresponding with the taxomy term
2. Added a cck field with true and false option and set it for one node of each taxonomy term
3. Created a view with the fields taxonomy:term and in my case taxonomy: Term image
4. Added a filter to view taxonomy term and an extra filter to check if the cck field of the content type is true

Kinda bussy right now, hope you understand it :)

Cheers
Henk

voodootea’s picture

great, thanks for that, i used your first suggestion, (except i used a node view as term view as suggested didnt work):


1) create a new Term View (not a Node View like most people tend to use and like the previous method below)
2) add the Taxonomy Term to the list of Fields
3) Add a relationship "Taxonomy: Node" and make it obligatory
4) Add some filters to narrow the results as needed. (i.e. only nodes from a certain content type)

ellieelectrons’s picture

Just wanted to let you know that I've tried the first way documented and checked it twice, I still get duplicates. Am about to try the original way. Just wanted to record this here. I think, because of how this recipe has been updated over time there is some ambiguity about which method the comments are referring to. Just to be clear, the method I am referring, is as follows:

After a couple of months a much, much easier way of doing this became available thanks to joel_guesclin and merlinofchaos:
1) create a new Term View (not a Node View like most people tend to use and like the previous method below)
2) add the Taxonomy Term to the list of Fields
3) Add a relationship "Taxonomy: Node" and make it obligatory
4) Add some filters to narrow the results as needed. (i.e. only nodes from a certain content type)

Ellie.

P.S. Also wanted to say (despite the problems I'm having), thank you for putting this together. This has been causing me some heartache!

Update 25 January 2011
Oops! Just realised my mistake... should have seen it amongst other comments. I had to find the distinct section in the basic settings section. I hadn't noticed this option before so I didn't know to look for it. Setting that Distinct option to yes worked for me.

RedTop’s picture

Hi Ellie,

I have added headers to the text. I agree the text had become harder to read over the months.

Which solution are you using? I understand you have opted to use the (newer) Term View solution and had to tick the 'use distinct' option. Is that correct? If so I will add it to the recipe.

ushasharma84’s picture

I have created a view to Browse the content by Ctaegory. I want to display Count along with term. How to do that.
Thanks in advance

netourish’s picture

Hi

I am having issues with building a heirarchical taxonomy menu/list with views.

I have managed to build one with the "taxonomy module", but it does not provide any options to customize it, like specially I want the menu to be collapsible.

I have also managed to build one with the views and editing the views theme template file template file, Again stuck at furthur disigning it to make it collpsible.

Suppose the menu is something like this :-

+ Music

  1. Istrumental
  2. Rock

+ Test

  1. Test1
  2. Test2

When the "+" beside the "Test" option is clicked then the display should be something like this :-

+ Music

  1. Istrumental
  2. Rock

- Test

Can this be achevable? Waiting for all your guidance/suggestions.

Thanking you all,
Pradeep.

netourish’s picture

Hi to everyone,

I was able to acheive the above mentioned requirement after hard research and found the "nice menu" module, this did not exactly met my requirement but this was something similar to which I wanted the display of the taxonomy listing.

emkamau’s picture

these solutions don't work for me in D7. when I follow the simple solution I get all my second level terms but not the first level. So I'm able to get all terms or only second level terms but not first level terms.

emk

joomlerrostov’s picture

I solved duplicates situation with 2 taxonomy vocabulares, and 2 terms from different vocabulares assigned to node.
In my node fields settings I created cck field of type "Conent taxonomy" with reference to first vocabulary. Second vocabulary is assigned via standard way. Then i created a view, and added in filters option: Content: content taxonomy field (attention, not a standard Taxonomy options like "Taxonomy: Term" and others).

It works!

ptsai’s picture

used the term view solution and was able to apply it to the slidedeck view to create exactly what i wanted. racked my brain all day, and your solution only took 2 minutes. you rule, thanks again.

druvision’s picture

In drupal 7 (views 3.x), the simplest way is to have a view on taxonomy terms, then use the views_view_field module to add a view field, pointing to another view which will select the things to display.

Follow my note here (http://drupal.org/node/1417090#comment-5890896) for more information.

Steps to follow:

1. Create a view on a taxonomy term.
2. Create a 2nd view to select the latest node for a taxonomy term (set the taxonomy term id as a contextual filter).
3. Add a view field to the 1st view, which will pass the term id as a parameter. The view field will link to the 2nd view and display the 2nd view.

mazharoddin’s picture

hi Amnon,

I tried as you mentioned, but it is not working in Drupal 7, can you please provide instructions again, am stuck with second view, second" view is always blank, and I am unable to find taxonamy term id in contextual filter, I can see only "Content: Has taxonomy term ID " or "Content: Category " options in contextual filter, please help me to resolve this issue,your help is greatly appreciated

-Mazhar

IWasBornToWin’s picture

The simple solution doesn't work for d7. But this does:

Create a view of terms
add taxonomy field, im using all term but your field will work.
add relationship - Taxonomy term:content using [name of your field] - mine is named "category"

Then under what is being referred to all over this post as "basic settings" is "query settings", choose distinct, then "pure distinct"

That should be it. I even have to other relationships addes for content author and other user's which match the category. I use the view to show user's nodes which match a category they've chosen in their user field.

Here is an export of the view:

$view = new view();
$view->name = 'taxonomy_without_duplicates';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'taxonomy_term_data';
$view->human_name = 'Taxonomy without duplicates';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Notify category match';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['query']['options']['distinct'] = TRUE;
$handler->display->display_options['query']['options']['pure_distinct'] = TRUE;
$handler->display->display_options['query']['options']['query_tags'] = array(
0 => 'Array',
);
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '0';
$handler->display->display_options['pager']['options']['offset'] = '0';
$handler->display->display_options['pager']['options']['id'] = '0';
$handler->display->display_options['pager']['options']['quantity'] = '9';
$handler->display->display_options['style_plugin'] = 'table';
$handler->display->display_options['style_options']['columns'] = array(
'name_1' => 'name_1',
'name' => 'name',
'title' => 'title',
'title_field' => 'title_field',
'body' => 'body',
'field_first_name' => 'field_first_name',
'uid' => 'uid',
'uid_1' => 'uid_1',
);
$handler->display->display_options['style_options']['default'] = '-1';
$handler->display->display_options['style_options']['info'] = array(
'name_1' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'name' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'title' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'title_field' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'body' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'field_first_name' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'uid' => array(
'align' => '',
'separator' => '',
'empty_column' => 0,
),
'uid_1' => array(
'sortable' => 0,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => 0,
),
);
/* Relationship: Taxonomy term: Content using Category */
$handler->display->display_options['relationships']['reverse_field_category_node']['id'] = 'reverse_field_category_node';
$handler->display->display_options['relationships']['reverse_field_category_node']['table'] = 'taxonomy_term_data';
$handler->display->display_options['relationships']['reverse_field_category_node']['field'] = 'reverse_field_category_node';
$handler->display->display_options['relationships']['reverse_field_category_node']['required'] = TRUE;
/* Field: Content: Post date */
$handler->display->display_options['fields']['created']['id'] = 'created';
$handler->display->display_options['fields']['created']['table'] = 'node';
$handler->display->display_options['fields']['created']['field'] = 'created';
$handler->display->display_options['fields']['created']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['fields']['created']['label'] = 'Date';
$handler->display->display_options['fields']['created']['date_format'] = 'custom';
$handler->display->display_options['fields']['created']['custom_date_format'] = 'm/d/y';
/* Field: Content: Title */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'node';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['relationship'] = 'reverse_field_category_node';
/* Field: Content: Title */
$handler->display->display_options['fields']['title_field']['id'] = 'title_field';
$handler->display->display_options['fields']['title_field']['table'] = 'field_data_title_field';
$handler->display->display_options['fields']['title_field']['field'] = 'title_field';
$handler->display->display_options['fields']['title_field']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['fields']['title_field']['label'] = '';
$handler->display->display_options['fields']['title_field']['exclude'] = TRUE;
$handler->display->display_options['fields']['title_field']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['title_field']['link_to_entity'] = 1;
/* Field: Content: All taxonomy terms */
$handler->display->display_options['fields']['term_node_tid']['id'] = 'term_node_tid';
$handler->display->display_options['fields']['term_node_tid']['table'] = 'node';
$handler->display->display_options['fields']['term_node_tid']['field'] = 'term_node_tid';
$handler->display->display_options['fields']['term_node_tid']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['fields']['term_node_tid']['label'] = 'Category';
$handler->display->display_options['fields']['term_node_tid']['vocabularies'] = array(
'forums' => 0,
'admin_forum' => 0,
'listings' => 0,
'notify' => 0,
'partipcation' => 0,
'tags' => 0,
'trading' => 0,
'userpoints' => 0,
);
/* Field: Content: Body */
$handler->display->display_options['fields']['body']['id'] = 'body';
$handler->display->display_options['fields']['body']['table'] = 'field_data_body';
$handler->display->display_options['fields']['body']['field'] = 'body';
$handler->display->display_options['fields']['body']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['fields']['body']['exclude'] = TRUE;
/* Field: Content: Type */
$handler->display->display_options['fields']['type']['id'] = 'type';
$handler->display->display_options['fields']['type']['table'] = 'node';
$handler->display->display_options['fields']['type']['field'] = 'type';
$handler->display->display_options['fields']['type']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['fields']['type']['exclude'] = TRUE;
/* Sort criterion: Content: Post date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'node';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['relationship'] = 'reverse_field_category_node';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';

Yorgg’s picture

Is this stopping terms to be duplicated in case you are importing them programmatically?

xbrianx’s picture

was trying to figure out where the 'distinct' button was and found it under advanced settings -> Query Options

marameodesign’s picture

I can confirm this works well.

Just a clarification, you'll have to add Content:All taxonomy terms (and then hide the field if you wish) to make this work.

Thanks!

bikramth19’s picture

I was used to design a website using the drupal6 & now migrating to drupal7. There's lots of different in drupal6 & drupal7.

I feel very comfortable to used the tutorial which I got. Thanks to this post.

lzimmerman’s picture

In working with a site with 50-100k nodes, I found that a block view of "content type X with term Y" was extremely slow. Disabling the 'Distinct' setting was faster, but permitted duplicates.

It can be possible to use aggregation as an alternative to the 'Distinct' checkbox.

Here are the steps I used:
- Uncheck 'Distinct' in Query Settings. Duplicates may now appear, in which case:
- Check "Aggregation" in the "Use Aggregation" setting. Errors may appear as fields haven't been updated.
- For each field displayed, click on "Aggregation settings" and select "Group Results Together."
If "Group Column" appears below the aggregation type, select "Entity ID."

Duplicates should vanish, and the query should be far more efficient.

If image fields do not appear (may affect other media also):
- Create a Relationship the file itself, e.g. "Field: Image:fid", labeled e.g. "Content Image"
- Add an fid field to view via that relationship, e.g.
"(Content Image) File: File ID (File ID)"
It's OK to exclude this field to display; it appears to associate the file w/ its content either way.

The view should now display as it did without aggregation, but in a reasonable query time.

Badlapje’s picture

All of the so far mentioned solutions seem to revolve around taxonomy terms that are used by nodes. I however had a use case where i had two vocabularies (A and B), with one of the vocabularies (B) having a term reference to the other (A). I wanted a list of all terms in A that were used by B.

So here's how i did it:
1) set up a term view of B
2) in included fields remove the default and add Taxonomy Term: A
3) under advanced > other set Use aggregation to yes
4) under aggregation settings of the field (now newly appeared):
a) set aggregation type to "group results together"
b) set group column to "tid"

Hope it helps for those looking for a similar list.

tjnormington’s picture

I was struggling with setting this up in Drupal 8 but I was able to figure it out, here is how I configured my view.

1. Create a Taxonomy View
2. My setup requires I use a field instead of just outputting the term, so I switched it over to show Fields
3. Add a relationship for "Content using [field_name]"
4. In the Advanced Tab, toggle Distinct in the Query Settings
5. Turn on Use Aggregation

This should limit the view to only show terms that are referenced by a node using a specified field.