This problem happens in some rare cases such as this one:

A view listing some contacts which are tagged with a geographical zone (city, region,...). There is an exposed filter "Geographical zone" whose widget is autocompletion (better because there are numerous zones).
The zones can be countries ('France', 'Belgium',...), regions ('Nord',...), cities ('Lille', 'Valenciennes',...) or even districts ('Lille - Vauban', 'Lille - Centre',...). Some big cities have many districts.
As a user of the view, I want to filter the list to show all the contacts in Lille. When I type "Lill" or even "Lille" in the autocomplete field, the districts ('Lille - Vauban',...) are suggested before the city. And as there are more than 10 districts, the city does not ever appear in the suggestions.
This is confusing. People can believe that they can't filter on 'Lille'.

-> That's why we'd need to order the results so that the exact match always appear if it exists.
An easy way to do this is to order the suggestions by length. Here's the code to add to views_ajax_autocomplete_taxonomy() :

    // Unsure the exact (=shorter) match is displayed.
    $query->addExpression('LENGTH(t.name)', 'length');
    $query->orderBy('length', 'ASC');

There could be other ways to do the same. I'm especially wondering if the use of LENGTH() is possible, regarding the different data backends available.
Any thoughts?

Comments

cafuego’s picture

This also occurs in panopoly, where an item is content is selected via a views "title contains" query. The result list is ordered by order in the database, which means that if you try to reference a node whose title is a substring of one or more other nodes, you always end up selecting the first match, ie: the oldest node.

This code sorts by exact match first, then by matched title length.

/**
 * Implements hook_views_query_alter()
 */
function match_sort_views_query_alter(&$view, &$query) {
  if ($view->name == 'whatevs' && $view->current_display == 'selectything') {
    // Exact match sort.
    if (!empty($view->exposed_data['title'])) {
      $query->orderby[] = array('field' => "(node_title = '" . $view->exposed_data['title']. "')", 'direction' => 'DESC');
    }
    // Length of matched title sort.
    $query->orderby[] = array('field' => 'LENGTH(node_title)', 'direction' => 'ASC');
  }
}
lsolesen’s picture

Patch missing?

cafuego’s picture

No patch, that's a snippet from a custom module to override the query sort for a specific display of a specific view.

cafuego’s picture

Chris Matthews’s picture

Status: Needs review » Closed (outdated)