Jump to content
dreerr

Get Pages with the most similar Categories (sorted)

Recommended Posts

Okay maybe this is a bit too complicated, but it could be my first attempt for a module:

In this case I have videos with categories attached through a page field. Example:

Video1: Categories: Nature, Flowers, Red

Video2: Categories: Nature, Weather, Blue

Video3: Categories: Nature, Stone, Red

In the video Template I want to display related clips, sorted by most similar categories.

If I see Video1 the similar videos should be: Video3, then Video2.

My attempt would be to make multiple find() with a combination algorithm, abstracted like here:

Array
(
    [0] => Array ( [0] => a [1] => b [2] => c [3] => d )
    [1] => Array ( [0] => a [1] => b [2] => c )
    [2] => Array ( [0] => a [1] => b [2] => d )
    [3] => Array ( [0] => a [1] => c [2] => d )
    [4] => Array ( [0] => b [1] => c [2] => d )
    [5] => Array ( [0] => a [1] => b )
    [6] => Array ( [0] => a [1] => c )
    [7] => Array ( [0] => a [1] => d )
    [8] => Array ( [0] => b [1] => c )
    [9] => Array ( [0] => b [1] => d )
    [10] => Array ( [0] => c [1] => d )
    [11] => Array ( [0] => a )
    [12] => Array ( [0] => b )
    [13] => Array ( [0] => c )
    [14] => Array ( [0] => d )
)

But I would have 14 queries with only 4 categories!

There must be a better solution, I can't think of now, what am I missing?

Share this post


Link to post
Share on other sites

Maybe:

$categories = $page->categories;
$relatedVideos = $pages->find("template=video, categories={$categories}");

//Don't know 100% if this is possible with pw:
$relatedVideos->sort("-categories.count");
foreach ($relatedVideas as $v) {
//..print
}

//If the above does not work, add the videos to an array and sort this with PHP's ksort
$videos = array();
foreach ($relatedVideos as $v) {
  $videos[count($v->categories)] = $v;
}

//Sort array by keys
ksort($videos);

//Access the keys in reverse order
$count = count($videos)-1;
for ($i=$count; $i>=0, $i--) {
//..print
}

Does it work?

  • Like 1

Share this post


Link to post
Share on other sites

http://processwire.com/talk/topic/745-module-want-related-pages/page-3

Actually you can just do 

$articles = $pages->find("category=$cat, limit=10");

It will return pages that have $cat sorted by score. $cat can also be a page array.  See edit

If you want to even go further and sort them also by modified date, take a look at the module I linked on top.

Edit: Actually looking at my module code again, this is the way using PW selector query only. But this way you can't sort them by more than 1 field and it's not near as optimized as the direct sql version.

foreach($tags as $tag) {
    $found = wire("pages")->find("categories=$tag, id!=$page->id, limit=$limit");
    foreach($found as $r) $rel[$r->id]++;
}

// build PageArray and add "score" property
$pa = new PageArray();
foreach($rel as $key => $score) {
    $pa->add( wire('pages')->get($key)->set("score",$score) );
}
 

Now $pa hold the pages and can be sorted by "-score"

  • Like 1

Share this post


Link to post
Share on other sites

To both of you: Grüezi from Vienna  :)

@Soma:

Yes this is of course a better approach to set a score and then sort by it.

Already have it up and running, works like a charm :)

@Wanze:

I'm sorry I haven't tried your method, because I was unsure if it really counted only the related categories or all of them.

Glad to be on ProcessWire, will make a T-Shirt  ^_^

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...