【问题标题】:Sphinx Query is returning null results in PHPSphinx Query 在 PHP 中返回空结果
【发布时间】:2021-08-20 23:03:09
【问题描述】:

我目前正在使用 PHP 从我的 sphinx 索引中查询。索引正在正确构建,但搜索却没有。

最初我的查询设置如下:

private function _doMapSearchAll($textSearch, $typeFilterArr, $rads = array(), $centre = array(), $showFavourites = false) {
    // lookup the location based on the search and return the results in that
    // map bounds ignore for boundary searches
    $rsArr = array();
    $skipDataSearch = false;
    if (!COUNT($rads)) {
      // handle airport code lookups if we have 3 characters
      if (strlen($textSearch) === 3) {
        $rsArr = $this->_doMapAirportSearch($textSearch);
        if (COUNT($rsArr)) {
          $skipDataSearch = true;
        }
      }
      // still no results based on the above search, do generic map search
      if ($skipDataSearch === false) {
        $rsArr = $this->_doMapGeoSearch($textSearch, $typeFilterArr, $centre);
        if (COUNT($rsArr['results']) > 0) {
          $skipDataSearch = false;
        }
      }
    }

    // if we are doing a boundary search, or we have no results from the above,
    // get all results based on our location
    if ($skipDataSearch === false) {
      // fall back onto searching via the data
      // normalise the search string
      $originalSearchString = $this->doNormalisation($textSearch);
      // use sphinx for the search
      $sphinx = $this->_getSphinxConnection();
      $sphinx->setLimits(0, $this->container->getParameter('search_max_results'), $this->container->getParameter('search_max_results'));
      if (COUNT($typeFilterArr)) {
        $sphinx->SetFilter('fldSiteTypeUID_attr', $typeFilterArr);
      }

      // if we're doing a boundary search, skip the search string
      if (COUNT($rads) > 0) {
        $originalSearchString = '';
        if ($showFavourites === false) {
          //$sphinx->SetFilterFloatRange('lat_radians', min($rads['minLat'], $rads['maxLat']), max($rads['minLat'], $rads['maxLat']));
          //$sphinx->SetFilterFloatRange('long_radians', min($rads['minLon'], $rads['maxLon']), max($rads['minLon'], $rads['maxLon']));

          if ($rads['minLat'] > $rads['maxLat']) {
            $rads['minLat'] = $rads['minLat'] - 360;
          }
          if ($rads['minLon'] > $rads['maxLon']) {
            $rads['minLon'] = $rads['minLon'] - 180;
          }

          $sphinx->SetFilterFloatRange('lat_radians', $rads['minLat'], $rads['maxLat']);
          $sphinx->SetFilterFloatRange('long_radians', $rads['minLon'], $rads['maxLon']);
        }
      }

      // order by centre point
      if (COUNT($centre) > 0) {
        // otherwise start in the centre
        $sphinx->SetGeoAnchor('lat_radians', 'long_radians', (float) $centre['centreLat'], (float) $centre['centreLon']);
        $lintDistanceLimit = 999999999.0; // everything
        if ($showFavourites === false && isset($rads['maxLat'])) {
          $radiusMiles = $this->get('geolocation_helper')->getSeparation(
            rad2deg($rads['maxLat']),
            rad2deg($rads['minLon']),
            rad2deg($rads['minLat']),
            rad2deg($rads['maxLon']),
            "M"
          );
          $lintDistanceLimit = $radiusMiles * 1609; // miles to meters...
        }
        $sphinx->SetFilterFloatRange('geodist', 0.0, (float)$lintDistanceLimit);
        $sphinx->SetSortMode(SPH_SORT_EXTENDED, 'geodist ASC');
      } else {
        // apply search weights
        $sphinx->SetFieldWeights(array('fldTown_str' => 100, 'fldAddress1_str' => 30, 'fldSiteName_str' => 20));
      }

      // if we should be limiting to only favourites, pickup the selected
      // favourites from cookies
      if ($showFavourites === true) {
        $request = $this->container->get('request_stack')->getCurrentRequest();
        $favourites = explode(',', $request->cookies->get('HSF_favlist'));
        if (count($favourites)) {
          foreach ($favourites as $k => $favourite) {
            $favourites[$k] = (int)$favourite;
          }
          $sphinx->SetFilter('fldUID_attr', $favourites);
        }
      }
      $rs = $sphinx->Query($originalSearchString, $this->container->getParameter('sphinx_index'));
      echo json_encode($sphinx);
      $rsArr['results'] = array();
      if (isset($rs['matches']) && count($rs['matches'])) {
        // update the search text to what we actually searched for, this
        // is needed in case we've updated/set $rsArr['searchText']
        // after a geolookup
        $rsArr['searchText'] = $textSearch;
        // clear any previous bounds set by the geolookup, we don't want this
        // if we have direct text match results
        $rsArr['geobounds'] = array();
        if (isset($rs['matches']) && count($rs['matches'])) {
          foreach ($rs['matches'] as $k => $match) {
            $rsArr['results'][$k] = $this->_remapSphinxData($k, $match);
          }
        }

        // sort the results by distance
        usort($rsArr['results'], function ($a, $b) {
          return $a['fldDistance'] - $b['fldDistance'];
        });
      }
    }

    // add on the total record count
    $rsArr['total'] = (int) COUNT($rsArr['results']);

    return $rsArr;
  }

这没有返回任何东西,并给了我 GEODIST() 的错误:

{"_host":"sphinx","_port":36307,"_path":"","_socket":false,"_offset":0,"_limit":250,"_mode":0,"_weights":[],"_sort":4,"_sortby":"geodist ASC","_min_id":0,"_max_id":0,"_filters":[{"type":2,"attr":"geodist","exclude":false,"min":0,"max":999999999}],"_groupby":"","_groupfunc":0,"_groupsort":"@group desc","_groupdistinct":"","_maxmatches":"250","_cutoff":0,"_retrycount":0,"_retrydelay":0,"_anchor":{"attrlat":"lat_radians","attrlong":"long_radians","lat":0.9300859583877783,"long":-2.0943951023931953},"_indexweights":[],"_ranker":0,"_rankexpr":"","_maxquerytime":0,"_fieldweights":[],"_overrides":[],"_select":"*","_error":"searchd error: geoanchor is deprecated (and slow); use GEODIST() expression","_warning":"","_connerror":false,"_reqs":[],"_mbenc":"","_arrayresult":false,"_timeout":0}{"results":[],"bounds":{"bllat":53.395603,"trlat":53.7159857,"bllng":-113.7138017,"trlng":-113.2716433},"geocentre":{"lat":53.5461245,"lon":-113.4938229},"checksum":"204a43923452936b00a10c8e566c4a48d4fdb280f97fd4042646eb45c8257bbc","searchText":"Edmonton, AB, Canada","skipResults":true,"showFavourites":false}

为了解决这个问题,我将 SetGeoAnchor 函数更改为以下内容:

  private function _doMapSearchAll($textSearch, $typeFilterArr, $rads = array(), $centre = array(), $showFavourites = false) {
    // lookup the location based on the search and return the results in that
    // map bounds ignore for boundary searches
    $rsArr = array();
    $skipDataSearch = false;
    if (!COUNT($rads)) {
      // handle airport code lookups if we have 3 characters
      if (strlen($textSearch) === 3) {
        $rsArr = $this->_doMapAirportSearch($textSearch);
        if (COUNT($rsArr)) {
          $skipDataSearch = true;
        }
      }
      // still no results based on the above search, do generic map search
      if ($skipDataSearch === false) {
        $rsArr = $this->_doMapGeoSearch($textSearch, $typeFilterArr, $centre);
        if (COUNT($rsArr['results']) > 0) {
          $skipDataSearch = false;
        }
      }
    }

    // if we are doing a boundary search, or we have no results from the above,
    // get all results based on our location
    if ($skipDataSearch === false) {
      // fall back onto searching via the data
      // normalise the search string
      $originalSearchString = $this->doNormalisation($textSearch);
      // use sphinx for the search
      $sphinx = $this->_getSphinxConnection();
      $sphinx->setLimits(0, $this->container->getParameter('search_max_results'), $this->container->getParameter('search_max_results'));
      if (COUNT($typeFilterArr)) {
        $sphinx->SetFilter('fldSiteTypeUID_attr', $typeFilterArr);
      }

      // if we're doing a boundary search, skip the search string
      if (COUNT($rads) > 0) {
        $originalSearchString = '';
        if ($showFavourites === false) {
          //$sphinx->SetFilterFloatRange('lat_radians', min($rads['minLat'], $rads['maxLat']), max($rads['minLat'], $rads['maxLat']));
          //$sphinx->SetFilterFloatRange('long_radians', min($rads['minLon'], $rads['maxLon']), max($rads['minLon'], $rads['maxLon']));

          if ($rads['minLat'] > $rads['maxLat']) {
            $rads['minLat'] = $rads['minLat'] - 360;
          }
          if ($rads['minLon'] > $rads['maxLon']) {
            $rads['minLon'] = $rads['minLon'] - 180;
          }

          $sphinx->SetFilterFloatRange('lat_radians', $rads['minLat'], $rads['maxLat']);
          $sphinx->SetFilterFloatRange('long_radians', $rads['minLon'], $rads['maxLon']);
        }
      }

      // order by centre point
      if (COUNT($centre) > 0) {
        // otherwise start in the centre
        // $sphinx->SetGeoAnchor('lat_radians', 'long_radians', (float) $centre['centreLat'], (float) $centre['centreLon']);
        $centreLat = (float) $centre['centreLat'];
        $centreLon = (float) $centre['centreLon'];
        $sphinx->SetSelect("GEODIST(lat_radians, long_radians, $centreLat, $centreLon) AS geodist");
        $lintDistanceLimit = 999999999.0; // everything
        if ($showFavourites === false && isset($rads['maxLat'])) {
          $radiusMiles = $this->get('geolocation_helper')->getSeparation(
            rad2deg($rads['maxLat']),
            rad2deg($rads['minLon']),
            rad2deg($rads['minLat']),
            rad2deg($rads['maxLon']),
            "M"
          );
          $lintDistanceLimit = $radiusMiles * 1609; // miles to meters...
        }
        $sphinx->SetFilterFloatRange('geodist', 0.0, (float)$lintDistanceLimit);
        $sphinx->SetSortMode(SPH_SORT_EXTENDED, 'geodist ASC');
      } else {
        // apply search weights
        $sphinx->SetFieldWeights(array('fldTown_str' => 100, 'fldAddress1_str' => 30, 'fldSiteName_str' => 20));
      }

      // if we should be limiting to only favourites, pickup the selected
      // favourites from cookies
      if ($showFavourites === true) {
        $request = $this->container->get('request_stack')->getCurrentRequest();
        $favourites = explode(',', $request->cookies->get('HSF_favlist'));
        if (count($favourites)) {
          foreach ($favourites as $k => $favourite) {
            $favourites[$k] = (int)$favourite;
          }
          $sphinx->SetFilter('fldUID_attr', $favourites);
        }
      }
      $rs = $sphinx->Query($originalSearchString, $this->container->getParameter('sphinx_index'));
      echo json_encode($sphinx);
      $rsArr['results'] = array();
      if (isset($rs['matches']) && count($rs['matches'])) {
        // update the search text to what we actually searched for, this
        // is needed in case we've updated/set $rsArr['searchText']
        // after a geolookup
        $rsArr['searchText'] = $textSearch;
        // clear any previous bounds set by the geolookup, we don't want this
        // if we have direct text match results
        $rsArr['geobounds'] = array();
        if (isset($rs['matches']) && count($rs['matches'])) {
          foreach ($rs['matches'] as $k => $match) {
            $rsArr['results'][$k] = $this->_remapSphinxData($k, $match);
          }
        }

        // sort the results by distance
        usort($rsArr['results'], function ($a, $b) {
          return $a['fldDistance'] - $b['fldDistance'];
        });
      }
    }

    // add on the total record count
    $rsArr['total'] = (int) COUNT($rsArr['results']);

    return $rsArr;
  }

这会给我返回结果,但是它们看起来像这样:

{"_host":"sphinx","_port":36307,"_path":"","_socket":false,"_offset":0,"_limit":250,"_mode":0,"_weights":[],"_sort":4,"_sortby":"geodist ASC","_min_id":0,"_max_id":0,"_filters":[{"type":2,"attr":"geodist","exclude":false,"min":0,"max":999999999}],"_groupby":"","_groupfunc":0,"_groupsort":"@group desc","_groupdistinct":"","_maxmatches":"250","_cutoff":0,"_retrycount":0,"_retrydelay":0,"_anchor":[],"_indexweights":[],"_ranker":0,"_rankexpr":"","_maxquerytime":0,"_fieldweights":[],"_overrides":[],"_select":"GEODIST(lat_radians, long_radians, 0.93008595838778, -2.0943951023932) AS geodist","_error":"","_warning":"","_connerror":false,"_reqs":[],"_mbenc":"","_arrayresult":false,"_timeout":0}{"results":[[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,34362776,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,38279990,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7963188,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7971966,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31790051,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7972301,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,33589292,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,33589642,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7962913,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31789941,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7962178,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,49484181,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31795436,null,""],

.....

我的搜索配置如下所示:

searchd
{
  listen            = 36307
  listen            = 9306:mysql41
  log               = /opt/sphinx/searchd.log
  query_log         = /opt/sphinx/query.log
  read_timeout      = 5
  max_children      = 30
  pid_file          = /opt/sphinx/searchd.pid
  seamless_rotate   = 1
  preopen_indexes   = 1
  unlink_old        = 1
  binlog_path       = /opt/sphinx/
}

我是新的 tp Sphinx,需要帮助更正此查询。有什么想法吗?

编辑:这是 sphinx 版本 3.4.1

【问题讨论】:

    标签: php mysql sphinx


    【解决方案1】:

    所以在过去几天的几个小时之后,我找到了答案......:

    我在声明中缺少*:

    $sphinx->SetSelect("*, GEODIST($centreLat, $centreLon, lat_radians, long_radians) as geodist");

    我希望这对将来遇到此问题的人有所帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-28
      • 2021-09-15
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多