How to exclude pages in Site wide Search

I have a simple site-wide search page. In my search.php controller, I’m attempting to have the search NOT include a page (‘members’) and its children pages. I tried ‘not’ method and ‘not in’ but it still searches all of the pages.

This code does NOT work:

$results = $site->search( $query, ‘title|text|blocks’ )->listed()->not([ page( ‘members’ ) ]);

I also tried this:

$results = $site->search( $query, ‘title|text|blocks’ )->listed()->filterBy( ‘pages’, ‘not in’, [ ‘members’ ]);

I know I can filter by templates and tags but is there a way to filter by pages or exclude certain pages when doing a site-wide search?

$excluded = page('members')->children();
$excluded = $excluded->add(page('members');
$results = $site->search( $query, ‘title|text|blocks’ )->listed()->not( $excluded);

Although it would probably make more sense to filter the page to search first, not the results?

Thank you for your quick response. I had to add the listed() method to be able to use the add() method. The page wouldn’t display even in debug mode. Not sure why that is because both the children() and listed() return the same type.

$excluded = page( 'members' )->children()->listed();
$excluded->add(page('members'));
    
$results = $site->search( $query, 'title|text|blocks' )->listed()->not( $excluded );

The above code works for the main page and its children, but it doesn’t exclude any grandchildren or any deeper subpages.

So I modified the code to use the index() method. That works. However, I know the index() method can be pretty heavy since it’s looking through the entire contents including files. Is there another way besides using that method to exclude the parent ‘members’ page and all of it’s subpages?

$excluded = page( 'members' )->index()->listed();

$results = $site->search( $query, 'title|text|blocks' )->listed()->not( $excluded );

The warning basically refers to using $site->index() in large installations. Of course, if you your members page also has thousands of subpages in the tree, you might run into the same issue. I hope, that is not the case, otherwise, you will have to cache the collection.

1 Like

Hi @texnixe and @dsim412,

can you tell me, how it is possible to include only published pages in search?

Where do i have to put the code in the search.php controller?

Thank you very much,

Roland.

A published page is a page that is either listed or unlisted and since drafts are not publicly accessible anyway, there is nothing special to do. Unless you mean only listed pages.

ah yes, i ment only listed pages. sorry.

the result should be, that unlisted pages are not shown.

And what’s your current search code?

what do you mean with search code?
when i go to the website “www.mywebsite.de
/search?q=abc” i only want listed sites with “abc” shown.
is this, what you mean?

No, I mean the code that is responsible for showing the search result, probably a controller /site/controllers/search.php. You did not develop the site then?

i did not develop. i use the awesome zero one plugin. But you give the right hint. In the /site/controllers/search.php i changed

$results = $site->index()->published()->bettersearch($query);

into

$results = $site->index()->listed()->bettersearch($query);

And this seems to work!!!

Thank you so much. You are awesome, too!!!

Has anything changed with Kirby 4?
I get an error message, if I extend the code in the controller:

Error thrown with message “Call to a member function children() on null”

Unfortunately, I could not find a working solution here in the forum to exclude several pages from the search. I also can’t find a description in the cookbook for the search function either.

Please tell me in which line in your code the error appears and what you have on that line.

The error message means that you are calling the children() method on a non-existing page object (null).

Thanks for your quick help.
This is the complete code:

/site/controllers/search.php

return function ($site) {

  $query = get('q');
  
  $excluded = page('aktionen')->children();
	$excluded = $excluded->add(page('aktionen'));
	$results = $site->search( $query, 'title|headline|subheadline|text|layout')->listed()->not($excluded);

  return [
    'query' => $query,
    'results' => $results,
  ];

};

This line triggers the error message:
$excluded = page('aktionen')->children();

The “aktionen” page contains subpages, so I don’t understand the error message.

Does this page really exist? With the slug aktionen, and as a folder directly in /content, not as child of another page?

1 Like

You have already given me the solution: I used the name of the blueprint/template, not the slug. Now the subpages no longer appear in the search. :clap:

You might want to consider using the UUID as a parameter for the page() helper instead of the slug, so that if the page is later renamed, it will still be found.

1 Like

Perfect! I’ll keep your tip in mind. In my case, this link will never change. But there will certainly be a situation where the UUID makes more sense instead of the slug.