11

Imagine I have a content type that has two fields of type category: one is a taxonomy Author and another one is a taxonomy Topics, these two taxonomies are unrelated, the only 'thing' they may have in common is the component itself.

Now we go to the website as a visitor, then when the visitor clicks on a given Author I want to create a list with all the Topics that are present in Components that also contain the specific Author.

I know I could create a query object with a criteria containing both keywords from the different taxonomies to check if it retrieves any values, the problem is that I would need to do that for every single topic i.e. Author and Topic1, Author and Topic2, Author and Topic 3 etc, in the end it may mean tens of queries which I obviously don't want to do.

As I see it the taxonomy API won't help because both taxonomies and thefore their keywords are completely unrelated. Any alternatives?

5 Answers5

3

If I understand your requirement correctly, you could get this using the combination of CategoryCriteria and KeywordCriteria.

CategoryCriteria to specify which category the content tagged to in this case Topics. KeywordCriteria to specify which category key value (e.g.; Author=Chris ).

     PublicationCriteria pubCriteria = new PublicationCriteria(59); // publication scope
     CategoryCriteria categoryCriteria = new CategoryCriteria("Topics");
     KeywordCriteria taxonomyKeywordCriteria = new KeywordCriteria("Author", "Chris");
     Criteria allCriteria = CriteriaFactory.And(
                          new Criteria[] { pubCriteria, 
                          CriteriaFactory.And(new Criteria[] { categoryCriteria, taxonomyKeywordCriteria }) } 
                          );

     Query allComps = new Query(allCriteria);
     string[] compIDs = allComps.ExecuteQuery();
     Response.Write("<br /> Legth : " + compIDs.Length );
Ram G
  • 4,829
  • 1
  • 16
  • 26
  • Hi Ram, that is is not a solution.... Jaime explained it really well: "What you want Asier are all the keywords that belong to the "Topics" category that have been used to tag content which is also tagged with a given "Author""... note Author and Topics are completely different Categories with completely different Keywords. Thanks anyways! – Asier Fernández Oct 25 '12 at 19:54
  • @Asier, That's what the code exactly does. `Topics` is a different category and `Author` is a different category. `CategoryCriteria` gives you the components that tagged with any of the keywords that belong to `Topics` category and the `KeywordCriteria` checks specifically `Author` Category with `keyword` value `Chris`. – Ram G Oct 25 '12 at 20:25
  • but you are retrieving the component URIs not the Topics, I need the list of unique Topics. I am not looking for components, I am looking for the Topics. I want ALL THE KEYWORDS tagging published content that has also been tagged by another keyword from a different category. – Asier Fernández Oct 25 '12 at 20:52
  • 4
    Ok. Is this something similar to `TagCloud` kind of.. check this doc http://sdllivecontent.sdl.com/LiveContent/content/en-US/SDL_Tridion_2011_SPONE/concept_1387717293704AB68CD5543850895B3E – Ram G Oct 25 '12 at 22:19
  • Oh yeah!!! That indeed looks like the answer and only with two DB hits, I will try it out tomorrow! Thank you very much for your help! – Asier Fernández Oct 25 '12 at 23:22
2

I believe you will need to make 2 KeywordCriteria

Criteria #1: Author = "Chris"

Criteria #2: Topic = "Topic1" or "Topic2" or "Topic3"

Then create a new AND criteria to combine the two

Hope that helps, please specify if you are using .NET or Java if you need some examples

Chris

Chris Summers
  • 10,153
  • 1
  • 21
  • 46
  • Thanks for the reply Chris. I am using .NET. Maybe I didn't explain myself properly but to be honest I find the scenario quite difficult to explain. The example you provided would allow me to get all the components categorized as "Chris" AND ("Topic1" OR "Topic2" etc...), but that is not what I need to do. I need to get the list of topics which have related content published AND that content has also been categorized as "Chris", I don't want to get components if not the list of Topics. I am still not sure if my explanation is clear enough. – Asier Fernández Oct 24 '12 at 22:29
  • Can you define "Related Content"? – Chris Summers Oct 24 '12 at 23:37
  • 2
    What you want Asier are all the keywords that belong to the "Topics" category that have been used to tag content which is also tagged with a given "Author", right? I don't think the API allows that directly. You'll need a work-around, something like publishing those relationships from the CMS in some way – Jaime Santos Alcón Oct 25 '12 at 05:04
  • Jaime! Thank you to help me explain myself man :) That's exactly what I want and I just cannot think of a way of doing that other than: create a query object with a criteria containing both keywords from the different taxonomies to check if it retrieves any values, the problem is that I would need to do that for every single topic i.e. Author and Topic1, Author and Topic2, Author and Topic 3 etc, in the end it may mean tens of queries which I obviously don't want to do. – Asier Fernández Oct 25 '12 at 07:51
  • Why don't you publish one XML DCP with the information? Too many combinations/components? – Jaime Santos Alcón Oct 25 '12 at 15:01
  • @Jaime, I thought about that in the first place but the usability would be bad... every time a component is published editors would need to republish the XML, using the event system could help. The potential issue here is performance, because the search will include pretty much every content type in the CMS, so effectively every time a component is published the taxonomies XML would be republished automatically or manually. I don't think that there is a solution elegant and light, but this is the closest we got ;) Of course there is always the NOT recommended and unsupported direct DB queries. – Asier Fernández Oct 25 '12 at 20:02
2

So you want to find all components that are tagged with a specific author and then find the corresponding Topic keyword relations of the found components?

The TaxonomyRelationManager should be able to help you here:

TaxonomyRelationManager manager = new TaxonomyRelationManager();
string[] contentWithThisAuthor = manager.GetTaxonomyContent(new Keyword(taxonomyUriOfAuthors, authorUri), false);
Keyword[] relatedTopics = manager.GetTaxonomyKeywords(taxonomyUriOfTopics, contentWithThisAuthor, new Keyword[] {}, null, 16);
Bjørn van Dommelen
  • 1,057
  • 7
  • 13
  • Thanks Bjorn, yes is just like that... this is actually very well documented here: http://sdllivecontent.sdl.com/LiveContent/web/ui.xql?action=html&resource=login.html&destination=/LiveContent/content/en-US/SDL_Tridion_2011_SPONE/concept_1387717293704AB68CD5543850895B3E – Asier Fernández Oct 26 '12 at 13:34
2

Based on the comment by Ram G and therefore taking as starting point the code example in live content, I have verified that the following solution works:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Tridion.ContentDelivery.Taxonomies;
using Tridion.ContentDelivery.DynamicContent.Query;
using Tridion.ContentDelivery.DynamicContent;

namespace Asier.Web.UI
{
    public class TagCloud : System.Web.UI.WebControls.WebControl
    {
        protected override void Render(HtmlTextWriter writer)
        {
            TaxonomyRelationManager relationManager = new TaxonomyRelationManager();
            TaxonomyFactory taxFactory = new TaxonomyFactory();

            string taxonomyUriWhichIWantTheKeywordsFrom = "tcm:69-265-512";

            String[] componentUris = GetComponentUris();
            String[] contextKeywordUris = GetKeywordUris();
            Keyword[] contextKeywordArray = GetKeywordsFromKeywordUris(taxFactory, contextKeywordUris);
            Keyword[] cloudFacets = relationManager.GetTaxonomyKeywords(taxonomyUriWhichIWantTheKeywordsFrom, componentUris, contextKeywordArray, new CompositeFilter(), 16);

            ProcessKeywords(cloudFacets);
        }

        private static string[] GetComponentUris()
        {
            // This should probably be replaced with a Query object that
            // retrieves the URIs dynamically 
            return new String[] { "tcm:69-3645-16", "tcm:69-3648-16", "tcm:69-3651-16" };
        }

        private static string[] GetKeywordUris()
        {
            // this should probably be passed in as a property of the control
            return new string[] { "tcm:69-3078-1024" };
        }

        private static Keyword[] GetKeywordsFromKeywordUris(TaxonomyFactory taxFactory, String[] contextKeywordUris)
        {
            Keyword[] contextKeywordArray = new Keyword[contextKeywordUris.Length];

            for (int i = 0; i < contextKeywordUris.Length; i++)
            {
                contextKeywordArray[i] = taxFactory.GetTaxonomyKeyword(contextKeywordUris[i]);
            }

            return contextKeywordArray;
        }        

        private static void ProcessKeywords(Keyword[] cloudFacets)
        {
            for (int i = 0; i < cloudFacets.GetLength(0); i++)
            {

                if (cloudFacets[i].ReferencedContentCount > 0)
                {
                    // Do whatever...
                }
            }
        }
    }
}
0

For creating the query object, take help of a component. In the component, add these categories in seperate fields : Topic (ListBox, with Multiple Selection) Author (Dropdown, with single selection...or as desired).

In your case, select all the listbox options for Topic. Suppose you have 3 keywords viz Topic 1,Topic 2,Topic 3.

So that keywords would be formed as:

KeywordCriteria topicCriteria1= new KeywordCriteria("Topic","Topic 1");
KeywordCriteria topicCriteria2= new KeywordCriteria("Topic","Topic 2");
KeywordCriteria topicCriteria3= new KeywordCriteria("Topic","Topic 3");

Criteria[] topicCriterias = {topicCriteria1,topicCriteria2,topicCriteria3};
Criteria OrCriteria = CriteriaFactory.Or(topicCriterias);


//Create Author Criteria
KeywordCriteria AuthorCriteria= new KeywordCriteria("Author","Author 1");

//And both results
mainCriteria =CriteriaFactory.And(AuthorCriteria, topicCriterias);

//Query
query.Criteria=mainCriteria;

For selecting all the Keywords related to topic, you can write a method instead of writting individually. Hope this helps.

Huston Lopes
  • 622
  • 4
  • 17
  • Thanks Huston but as Chris that is not the answer to my question. I want to get the list of TOPICS not the list of components that are categorized as beloging to Topic 1 or Topic 2 etc. I know how to create queries to get Components TCMs, and I know how to create complex queries... but that does't help to achieve what I am aiming for. Jaime as a comment on Chris' reply actually explained what I wasn't able to explain myself, hehe. – Asier Fernández Oct 25 '12 at 07:53