Jump to content

Get Pages with the most similar Categories (sorted)


dreerr
 Share

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?

Link to comment
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
Link to comment
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
Link to comment
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
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...