Topics - GetSortedTopics Multiple tags and/or

Plugin Development
  • So, I'm aware that you can call this nodebb core function

    topics.getSortedTopics()
    

    and send as a parameter tag or tags (array of tags), this function returns topics that have all the tags in the array, right?

    Is there a way to get topics that have at least 1 of the tags in the array?

  • It is not possible out of the box, you would have to write your own function or call topics.getSortedTopics() once for each tag and merge the results.

  • @baris this can work, but I need to paginate the results.

    So to get ALL the Topics from each one of the tags, and then merge those results, then sort this merged array (by recent/views/votes) and then just return the section of the array that meets the page I want to show.

    this can get slow, right?

    is there another way I can get this done? may be directly quering the DB? or a better way?

  • You can try doing a union, but the result would be sorted by topic creation date.

    db.getSortedSetRevUnion({
      sets: tags.map(tag => `tag:${tag}:topics`),
      start,
      stop,
    });
    
  • @baris what about doing something like this ?

    get all Tids that have each tag

    await getTids(params);
    

    then merge those results in a big Tids array

    then sort that array of Tids

    await sortTids(data.tids, params);
    

    then filter that sorted array

    await filterTids(data.tids.slice(0,meta.config.recentMaxTopics), params);
    

    then get all the topics from the filtered sorted array

    await getTopics(data.tids, params);
    

    what do you think?

  • Sure that works, it similar to how getSortedTopics works.

  • @baris I just noticed that all these functions

    await getTids(params);
    await sortTids(data.tids, params);
    await filterTids(data.tids.slice(0,meta.config.recentMaxTopics), params);
    await getTopics(data.tids, params);
    

    are not exported on the Topics module, I there is no way for me to use them without updating nodebb source code.

  • I suggest copying what you need to your plugin and modifying it, the reason I kept those private is so we can make changes to those functions without breaking plugins.

    For example you can't straight use getTids because it would only return topics that have all the tags.

  • @baris following up on this, I think i got this fixed the way I needed, but just in case, I would like to hear your opinion.

    So, I took src/topics/sorted.js in the nodebb source code, copied to my theme, and requiere my customSorted.js instead of nodebb's sorted.js

    That way I can make my custom updates to the nodebb core, without actually changing nodebb src code.

    Becuase of some requierement of the project im working, we are NOT using categories, so I just have setup 1 category, and all topics go to that category. So, when I do all queries I need to do to topics, I ALWAYS set 'cids' to the default category i've already setup.

    For this reason, when I do 'topics.getSortedTopics...' with cids = 2 , in the sordted.js file this function gets call 'async function getCidTids(params)'

    in that function, 'if (params.tags.length)' , in my case true when I call it with multiple tags, this get's fired 'return _.intersection(...await Promise.all(....'

    Changing that 'return _.intersection(...await Promise.all(....' to 'return _.union(...await Promise.all(....' fixes my problem. I've done some testings and all seems to be working just fine.

    Another function I got my eyes on in that same sorted.js file is

    const method = params.sort === 'old' ?
    			'getSortedSetIntersect' :
    			'getSortedSetRevIntersect';
    

    maybe to ?

    const method = params.sort === 'old' ?
    			'getSortedSetUnion' :
    			'getSortedSetRevUnion';
    

    any comments on these two things? Am I maybe breaking something I didn't noticed yet?

    Again, thanks for the help.

  • @sebastián-cisneros said in Topics - GetSortedTopics Multiple tags and/or:

    const method = params.sort === 'old' ?
    'getSortedSetUnion' :
    'getSortedSetRevUnion';

    Yeah you can change to this in getTagTids function if you want to get topics with any of the tags passed in.


Suggested Topics