Jump to content

Search with AND and EXCLUDE (NOT)


Recommended Posts

Hello together,

currently I’m working on some kind of enhanced search for pages->find in the FRONTEND and I like to ask if someone has a possible solution or hint on how to build it.

My problem is, I like to add search strings with a "+" or "-" in front of word and tell PW what to search and what not based on the input of the user.

Let say I have the following page tree

  — NYC, USA
  — Miami, USA
  — Tokyio, Japan
  — Berlin, Germany

Let’s say that all pages have more then one body text field but in one of them is a text that contains the words "Airport" and "Air-condition".

User enter the following text into an input field:
Airport air +USA -nyc

My preferences are:
1) find all Airports (or cities) with the word Airport or air in the title OR in the body text of the pages, also find part of the words like fair or air-condition
2) Filter the results of 1) and find only pages with the word USA inside
3) Filter the results of 2) and show only (exclude) the results with a word like nyc
As the result only Miami, USA will be displayed, because it got USA and NOT nyc and in the body text are the words Airport and air-condition.

For 1) I used the code (see below) from  @Mats suggestion https://processwire.com/talk/topic/10883-search-with-and-string/

It searches part of words in the title and body with OR. But what I’m looking for is, how can I search for pages that have the search term AND the term with a "+" before. It finds me Airport but it should only find Airport if +USA is inside title of body text.
And of course, how it is possible to exclude a word, for example with a "-" before the search term.

In spoken language it would be: :rolleyes:
Find anything with Airport or air. Show only results containing the word USA and exclude anything from the results with the word nyc.
In general, is it possible to exclude something from the search in pages->find and what could be a good start to code such a search function?

Thanks so much in advance!

        if($q) {
			$input->whitelist('q', $q);
        	$qs = explode(" ", $q);
        	foreach($qs as $key => $q){
          	$qs[$key] = $sanitizer->selectorValue($q);
    $selector = "template=print, title|body|body_2|body_3%=" . implode("|", $qs) . ", limit=50";
	$matches = $pages->find($selector);




Link to comment
Share on other sites



1) find all Airports (or cities) with the word Airport or air in the title OR in the body text of the pages, also find part of the words like fair or air-condition


template=airport|city, title|body%=air

u donut need.Airport bcoz u got %=air


2) Filter the results of 1) and find only pages with the word USA inside

template=airport|city, title|body%=air, title%=USA


3) Filter the results of 2) and show only (exclude) the results with a word like nyc

template=airport|city, title|body%=air, title%=USA, id!=[title%=nyc]

or.in pw v3 u can do  
template=airport|city, title|body%=air, title%=USA, title!%=nyc

Link to comment
Share on other sites

Guys, this is wonderful and so simple. I love PW!
!title%=nyc works like a charm!

In my case I needed to exclude not only from the title but also from some more fields, my thoughts, that this would work were wrong:


Instead someone must use:

!title%=word_to_exclude, !job_body%=word_to_exclude

It is possible to unify this, or is it the way PW works?

Link to comment
Share on other sites


!title%=word_to_exclude, !job_body%=word_to_exclude

What you've got above is an AND condition, which I think is what you want. You could also do this if preferred:



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

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By donatas
      how would I do a multi-language website search with just a selector?
      I have many multi-lang fields and I want to do a search through all of them at once and through all of their language values.
      Is there a "selector way" of doing this? Maybe something like `title|title:de|title:it`? It seems I have seen this somewhere a long time ago but can't find in any documentation or forum search...
      Or the only way of doing it is by running separate searches for each language with output formatting off and then consolidating it all in one single results array?
      Because I still want to give users a result, even if it is in another language than current $user. Visitors mostly will be searching for specific terms that are very similar in all languages, but might be not used in one language version of a single page, for example. Or the user might not have switched language tohis prefered and did the search first, etc.. (many use cases in my situation)
      $pages->find('title~='.$q) - maybe different operator is needed? /en/search/?q=visit = 1 results /it/search/?q=visit = 0 results Thanks for any advice!
    • By sebr
      In my search page, I used a selector like this :
      $searchQuery = $sanitizer->entities($input->get('q')); $searchQuery = $sanitizer->selectorValue($searchQuery); $selector = 'title|subtitle|summary|html_body_noimg~=' . $searchQuery; $matches = $pages->find($selector); I don't have the same results if $searchQuery contains accent or not.
      For example,
      with « bâtiment » I have no result with « batiment » I have onea result : « Les bâtiments et les smart-city » Normally I should have the same results? How can I do that ?
      Thanks for your help
    • By michelangelo
      Hello guys, I am building a sort of an archive. Relatively simple, although I have about 8000 records, each with 15 fields (text, int, images, url). I created a crude search system with a form (emulating the famous Skyscrapper example) to filter through the system. Everything works but it is quite slow... I have 2 questions which are related:

      1. How can I search through the database?
      2. What is a good practice to display many records like these?
      1. I am retrieving the results with
      $songs = $pages->findMany('template=nk-song'); Then I do a foreach to render them all. I am unsure if that is a good way. If I render all of them on the page, it creates thousands of divs with a bit of text, and this can take a while (10s-15s).
      2. This one is even worse :D as every time I retrieve my desired records with something like this:
      $page->find("field_to_search_through~=my_query_string") I get between 20 and 200, but when I render them I am creating iframes with YouTube videos and that can take up to 10s to finish. I "solved" it by only loading the iframes if they are in view with IntersectionObserver on the client-side. But I feel there is a more precise PHP / ProcessWire approach.
      Just to clarify, I started doing all of this custom rendering and querying because tools like ElasticSearch or SearchEngine were a bit complicated and I needed a simple to retrieve information and then display it in my own way.
      Thank you!
    • By snobjorn
      I have a website with multiple content types that I want to be accessible through search. I really like the live search on processwire.com, that sorts content types while typing. I tried to find the code to recreate this, with no luck. Does anyone know if this is jquery, specific jquery plugins, json/xml cached files, and what kind of PHP code is used? Any tip that point me in the right direction would be much apperciated.
      The search result listing seems fairly easy to create with sorting through parameters.
    • By Anders
      I want to allow full text search on my site. There is a very nice solution that comes right out of the box:
      $selector = "title|body~=$q, limit=50"; This works, but to make it even better I would want to give higher weight to pages where the search term occurs in the title, than if it just occurs in the body. After all, a page with the title "Wine from France" is probably the best match for the search "france wine". How do I accomplish this in ProcessWire?
      I can see three possible paths, but I am not very fond of any of them:
      Do a direct SQL query, circumventing the API, along these lines. But I would prefer to abstract away the database layout if at all possible. Use something like ElasticSearch, but to be honest that would be to complicated to set up and maintain in the long run. Make multiple lookups, first for matches in the title, then for matches in the body, and merge and sort in PHP. My suspicion is that this would get complicated quite quickly. For instance, how do you deal with a page that has two of the three search terms in the title and the third in the body? Is there a magic option four I should look into? Or are any of the above options better than the others? Any input is welcome!
  • Create New...