Filtering titles of dataobjects from a specific page type

So, I think what I am trying to do should be simple… But it’s giving me some serious headaches! I created a Knowledge Base that has individual topics (dataobjects with links) and release notes (dataobjects without links). Currently my site filter works great with the topics. I can search for a title with partial match, and link to the page with ease, because each topic has a unique url. HOWEVER… I want to add the release note titles into my search, but I would need to link to their parent page, I cannot seem to get this working correctly.

My working code is:

public function index(HTTPRequest $request){
	$topics = Topic::get();
	if ($search = $request->getVar('Keywords')) {
	    	$topics = $topics->filter(array(
	      		'Title:PartialMatch' => $search             
		));
	}
	$paginatedTopics = PaginatedList::create(
        	$topics,
        	$request
  	)
 	 ->setPageLength(10)
	 ->setPaginationGetVar('s');

	 return [
	   	    'Results' => $paginatedTopics
	 ];
}

This changed code seems to break the whole thing:

public function index(HTTPRequest $request){
	$topics = Topic::get();
	$rnotes = ReleaseNote::get();

	$list = new ArrayList();
	$list->merge($topics);
	$list->merge($rnotes);

	if ($search = $request->getVar('Keywords')) {
    		$list = $list->filter(array(
      			'Title:PartialMatch' => $search             
		));
	}

	$paginatedTopics = PaginatedList::create(
       		$list,
       		$request
	)
   	->setPageLength(10)
  	->setPaginationGetVar('s');

        return [
      	    'Results' => $paginatedTopics
   	];
}

Any idea what I am doing wrong?

Nothing is standing out… have you inspected $list after merging in the datalists as well as after filtering to make sure it contains everything it’s supposed to? And if you take out the pagination part does it work okay?

By the way, be aware that by doing your filtering after pushing to an ArrayList you’re forcing this page to load every object that exists for those data types in to memory. If we pretend the code is working for a second, rearranging things so the filtering happens at the ORM level should be a lot more efficient (although still potential to load a lot of records):

$topics = Topic::get();
$rnotes = ReleaseNote::get();

if ($search = $request->getVar('Keywords')) {
    $topics = $topics->filter(array(
        'Title:PartialMatch' => $search             
    ));
    $rnotes = $rnotes->filter(array(
        'Title:PartialMatch' => $search             
    ));
}

$list = new ArrayList();
$list->merge($topics);
$list->merge($rnotes);

If it doesn’t mess up your model, it might suit you to create a base class (e.g. KnowledgeBaseItem) that has a Title field and any other common properties that Topics and ReleaseNotes share, and then have those two classes extend from the base class. Then you can use your original code and substitute in KnowledgeBaseItem::get(), and you should get better performance as only max 10 records at a time (your pagination page length) will be pulled from the database.