diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2840,6 +2840,7 @@ 'PhabricatorFerretFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorFerretFulltextEngineExtension.php', 'PhabricatorFerretFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php', 'PhabricatorFerretInterface' => 'applications/search/ferret/PhabricatorFerretInterface.php', + 'PhabricatorFerretMetadata' => 'applications/search/ferret/PhabricatorFerretMetadata.php', 'PhabricatorFerretNgrams' => 'applications/search/ferret/PhabricatorFerretNgrams.php', 'PhabricatorFerretSearchEngineExtension' => 'applications/search/engineextension/PhabricatorFerretSearchEngineExtension.php', 'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php', @@ -8175,6 +8176,7 @@ 'PhabricatorFerretField' => 'PhabricatorSearchDAO', 'PhabricatorFerretFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorFerretFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', + 'PhabricatorFerretMetadata' => 'Phobject', 'PhabricatorFerretNgrams' => 'PhabricatorSearchDAO', 'PhabricatorFerretSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorFile' => array( diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php --- a/src/applications/differential/query/DifferentialRevisionQuery.php +++ b/src/applications/differential/query/DifferentialRevisionQuery.php @@ -320,7 +320,7 @@ */ protected function loadPage() { $data = $this->loadData(); - + $data = $this->didLoadRawRows($data); $table = $this->newResultObject(); return $table->loadAllFromArray($data); } diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php --- a/src/applications/maniphest/query/ManiphestTaskQuery.php +++ b/src/applications/maniphest/query/ManiphestTaskQuery.php @@ -247,6 +247,7 @@ break; } + $data = $this->didLoadRawRows($data); $tasks = $task_dao->loadAllFromArray($data); switch ($this->groupBy) { diff --git a/src/applications/search/ferret/PhabricatorFerretMetadata.php b/src/applications/search/ferret/PhabricatorFerretMetadata.php new file mode 100644 --- /dev/null +++ b/src/applications/search/ferret/PhabricatorFerretMetadata.php @@ -0,0 +1,41 @@ +engine = $engine; + return $this; + } + + public function getEngine() { + return $this->engine; + } + + public function setPHID($phid) { + $this->phid = $phid; + return $this; + } + + public function getPHID() { + return $this->phid; + } + + public function setRelevance($relevance) { + $this->relevance = $relevance; + return $this; + } + + public function getRelevance() { + return $this->relevance; + } + + public function getRelevanceSortVector() { + return id(new PhutilSortVector()) + ->addInt(-$this->getRelevance()); + } + +} diff --git a/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php b/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php --- a/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php +++ b/src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php @@ -52,6 +52,7 @@ $viewer = PhabricatorUser::getOmnipotentUser(); $type_results = array(); + $metadata = array(); foreach ($type_map as $type => $spec) { $engine = $spec['engine']; $object = $spec['object']; @@ -83,6 +84,8 @@ $results = $engine_query->execute(); $results = mpull($results, null, 'getPHID'); $type_results[$type] = $results; + + $metadata += $engine_query->getFerretMetadata(); } $list = array(); @@ -90,6 +93,16 @@ $list += $results; } + // Currently, the list is grouped by object type. For example, all the + // tasks might be first, then all the revisions, and so on. In each group, + // the results are ordered properly. + + // Reorder the results so that the highest-ranking results come first, + // no matter which object types they belong to. + + $metadata = msort($metadata, 'getRelevanceSortVector'); + $list = array_select_keys($list, array_keys($metadata)) + $list; + $result_slice = array_slice($list, $offset, $limit, true); return array_keys($result_slice); } diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -31,6 +31,7 @@ private $ferretTokens = array(); private $ferretTables = array(); private $ferretQuery; + private $ferretMetadata = array(); protected function getPageCursors(array $page) { return array( @@ -82,6 +83,18 @@ return $this->beforeID; } + final public function getFerretMetadata() { + if (!$this->supportsFerretEngine()) { + throw new Exception( + pht( + 'Unable to retrieve Ferret engine metadata, this class ("%s") does '. + 'not support the Ferret engine.', + get_class($this))); + } + + return $this->ferretMetadata; + } + protected function loadStandardPage(PhabricatorLiskDAO $table) { $rows = $this->loadStandardPageRows($table); return $table->loadAllFromArray($rows); @@ -111,6 +124,27 @@ $this->buildOrderClause($conn), $this->buildLimitClause($conn)); + $rows = $this->didLoadRawRows($rows); + + return $rows; + } + + protected function didLoadRawRows(array $rows) { + if ($this->ferretEngine) { + foreach ($rows as $row) { + $phid = $row['phid']; + + $metadata = id(new PhabricatorFerretMetadata()) + ->setPHID($phid) + ->setEngine($this->ferretEngine) + ->setRelevance(idx($row, '_ft_rank')); + + $this->ferretMetadata[$phid] = $metadata; + + unset($row['_ft_rank']); + } + } + return $rows; } @@ -172,6 +206,7 @@ if ($this->beforeID) { $results = array_reverse($results, $preserve_keys = true); } + return $results; }