Jump to content

Full text search that gives height weight to mathces in the title than in the body?


Anders
 Share

Recommended Posts

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:

  1. 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.
  2. Use something like ElasticSearch, but to be honest that would be to complicated to set up and maintain in the long run.
  3. 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!

Link to comment
Share on other sites

On 2/24/2020 at 8:40 AM, Anders said:

Is there a magic option four I should look into?

There's no magic option - you have to code your own search in the way that suits you.

If the number of search results is not huge and pagination is not required then you can get all the results where any field matches, and then divide off the pages that have matches in the title field, rendering those results before the others.

Otherwise you might want to use an SQL query, perhaps returning just an array of page IDs which you could then slice according to the pagination number and load to a PageArray via $pages->getById().

  • Thanks 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.
  • Similar Content

    • By Mika
      Hello, can I use the selector to extract only pages with page titles longer than 10 characters?
      I'm looking for a way to search directly without using the php foreach statement, as shown below.
              $result = $this->pages->find("template!=admin, has_parent!=2, include=all");
              foreach ($result as $page) {
                  if (strlen($page->title) > 10) {
                      $this->table[] = $page;
                  }
              }
       
    • By Guy Incognito
      I'm trying to build a search selector that includes a checkbox multiple option field (clinicdetails_specialisms). The whole selector works fine if I don't include the checkbox field. With it included I get errors like "Error: Exception: SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters (in wire/core/PageFinder.php line 627)".
      This is the selector as it currently stands.
      subscription_status=active,(template=user,clinicdetails_description|clinicdetails_short_description|clinicdetails_clinic_name|clinicdetails_first_name|clinicdetails_last_name*=$query),(clinicdetails_specialisms.title=$query) I've also tried setting the specialisms field in one string rather than groups and have also tried with/without the '.title' property.
      Oddly the selector works if specialisms is the only field being searched. It seems to fail when mixed with other selectors.
      Can anyone advise what stupid mistake I'm making!
    • By Ksenia
      Hello! 
      I have a weird situation going on with my selector field, which I can't really get. 
      I create an array of titles as filter using this logic:
      firstname=Mike|Steve id=123|124|125 title*=Red|Blue|Green This is the field I am logging: 

      It goes in a for loop till it looks like what you see on the screen.
      So, my code regarding the selector string looks like this:
      $output = ""; foreach ($allorganisations as $item){ $output .= "$item | "; echo "<div style='color:red;'>//output String://</div>"; echo $output; } $selector_org .= ", title=$output"; I also log the output just after the matched pages are selected to be sure:
      $matches = $pages->find($selector_org); echo $output; foreach ($matches as $match) { echo " <li><a href='$match->url'>$match->title</a></li>"; } But you can see that it doesn't select all four needed pages, only selects one of them.
      Yet when I copy this exact selector text and manually put it in my selector, it works great... I even copy extra space and "|" and all that, it is supposed to be identical. I am very confused, what is the difference between the code? 
      foreach ($allorganisations as $item){ $output .= "Institute for Scientific Research in Cosmic Anthropoecology | Institute for Scientific Research in Cosmic Anthropoecology | Stanford Research Institute | Institute for Scientific Research in Cosmic Anthropoecology | Stanford Research Institute | Institute of Clinical and Experimental Medicine | Institute for Scientific Research in Cosmic Anthropoecology | Stanford Research Institute | Institute of Clinical and Experimental Medicine | Cosmists | "; echo "<div style='color:red;'>//output String://</div>"; echo $output; } $selector_org .= ", title=$output"; } ------>
      If you see where I'm going wrong, please enlighten me. I am very puzzled with this behaviour . :--)
      Best,
      Ksenia
    • By donatas
      Hello,
      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)
      Example:
      $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 fruid
      I'm having and always have a hard time building PaginatedArrays, I never know where to put the "limit=24" selector so please enlighten me.
      Here's what I'm doing…
      $categories = $page->protable('start=0, limit=999999'); // this I need in order to retrieve the pages's "categories" and I don't know how to make use of $rows instead for that purpose because of this confusing limit-API $rows = $page->protable; // put ("limit=20") here? $custom = buildSelector($input, $rows); // this function returns an array of selectors depending on the user input $items = new PaginatedArray; // or here? // or here? $items->find("limit=20") // or like this? $items("limit=20") // or like this? $items = $items("limit=20") // or like this? $items = $items->find("limit=20") foreach ($rows as $r) : if ($custom->get('selector')->matches($r)) : $items->add($r); endif; endforeach; // or at this point? and then
      if ($items) { // or maybe somewhere here?     echo '<span class="grey">'.$items->getPaginationString(array(     'label' => 'entries',     'zeroLabel' => '0 entries', // 3.0.127+ only     'usePageNum' => false,     'count' => count($items),     'start' => $items->getStart(),     'limit' => count($items),     'total' => $items->getTotal()     )); and then of course…
      $pager = $modules->get("MarkupPagerNav"); echo '<div class="uk-flex uk-flex-center">'.$pager->render($items, $options).'</div>'; I'm out of ideas and confused cause it doesn't make sense to me either way.
      ____
      The buildSelector function above returns and array…
      $selected = new Selectors("$letter, $searchterm, $category"); $custom = new Wirearray; $custom->set('selector', $selected); $built->set('sort', $sort); return $custom; and each of the new selectors are basically strings ("category=whatever")
      Also, you cannot put the "sort=title" or whatever as a selector for the Selectors function (see above). Why, I know not.
      I don't know if that is the proper way but selecting kind of works now as opposed to many other ways I tried. Selectors always require a lot of trial and error, it seems to have a very sensitive API, always depends on double quotes, single quotes and how you concatenate.
      Thanks for help!
×
×
  • Create New...