@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Sort global fulltext results by overall relevance

Summary:
Ref T12819. Currently, under the Ferret engine, we query each application's index separately and then aggregate the results.

At the moment, results are aggregated by type first, then by actual rank. For example, all the revisions appear first, then all the tasks.

Instead, surface the internal ranking data from the underlying query and sort by it.

Test Plan: Searched for "A B" with a task named "A B" and a revision named "A". Saw task first. Broadly, saw mixed task and revision order in result sets.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12819

Differential Revision: https://secure.phabricator.com/D18551

+93 -1
+2
src/__phutil_library_map__.php
··· 2840 2840 'PhabricatorFerretFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorFerretFulltextEngineExtension.php', 2841 2841 'PhabricatorFerretFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php', 2842 2842 'PhabricatorFerretInterface' => 'applications/search/ferret/PhabricatorFerretInterface.php', 2843 + 'PhabricatorFerretMetadata' => 'applications/search/ferret/PhabricatorFerretMetadata.php', 2843 2844 'PhabricatorFerretNgrams' => 'applications/search/ferret/PhabricatorFerretNgrams.php', 2844 2845 'PhabricatorFerretSearchEngineExtension' => 'applications/search/engineextension/PhabricatorFerretSearchEngineExtension.php', 2845 2846 'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php', ··· 8175 8176 'PhabricatorFerretField' => 'PhabricatorSearchDAO', 8176 8177 'PhabricatorFerretFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 8177 8178 'PhabricatorFerretFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', 8179 + 'PhabricatorFerretMetadata' => 'Phobject', 8178 8180 'PhabricatorFerretNgrams' => 'PhabricatorSearchDAO', 8179 8181 'PhabricatorFerretSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 8180 8182 'PhabricatorFile' => array(
+1 -1
src/applications/differential/query/DifferentialRevisionQuery.php
··· 320 320 */ 321 321 protected function loadPage() { 322 322 $data = $this->loadData(); 323 - 323 + $data = $this->didLoadRawRows($data); 324 324 $table = $this->newResultObject(); 325 325 return $table->loadAllFromArray($data); 326 326 }
+1
src/applications/maniphest/query/ManiphestTaskQuery.php
··· 247 247 break; 248 248 } 249 249 250 + $data = $this->didLoadRawRows($data); 250 251 $tasks = $task_dao->loadAllFromArray($data); 251 252 252 253 switch ($this->groupBy) {
+41
src/applications/search/ferret/PhabricatorFerretMetadata.php
··· 1 + <?php 2 + 3 + final class PhabricatorFerretMetadata extends Phobject { 4 + 5 + private $phid; 6 + private $engine; 7 + private $relevance; 8 + 9 + public function setEngine($engine) { 10 + $this->engine = $engine; 11 + return $this; 12 + } 13 + 14 + public function getEngine() { 15 + return $this->engine; 16 + } 17 + 18 + public function setPHID($phid) { 19 + $this->phid = $phid; 20 + return $this; 21 + } 22 + 23 + public function getPHID() { 24 + return $this->phid; 25 + } 26 + 27 + public function setRelevance($relevance) { 28 + $this->relevance = $relevance; 29 + return $this; 30 + } 31 + 32 + public function getRelevance() { 33 + return $this->relevance; 34 + } 35 + 36 + public function getRelevanceSortVector() { 37 + return id(new PhutilSortVector()) 38 + ->addInt(-$this->getRelevance()); 39 + } 40 + 41 + }
+13
src/applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php
··· 52 52 $viewer = PhabricatorUser::getOmnipotentUser(); 53 53 54 54 $type_results = array(); 55 + $metadata = array(); 55 56 foreach ($type_map as $type => $spec) { 56 57 $engine = $spec['engine']; 57 58 $object = $spec['object']; ··· 83 84 $results = $engine_query->execute(); 84 85 $results = mpull($results, null, 'getPHID'); 85 86 $type_results[$type] = $results; 87 + 88 + $metadata += $engine_query->getFerretMetadata(); 86 89 } 87 90 88 91 $list = array(); 89 92 foreach ($type_results as $type => $results) { 90 93 $list += $results; 91 94 } 95 + 96 + // Currently, the list is grouped by object type. For example, all the 97 + // tasks might be first, then all the revisions, and so on. In each group, 98 + // the results are ordered properly. 99 + 100 + // Reorder the results so that the highest-ranking results come first, 101 + // no matter which object types they belong to. 102 + 103 + $metadata = msort($metadata, 'getRelevanceSortVector'); 104 + $list = array_select_keys($list, array_keys($metadata)) + $list; 92 105 93 106 $result_slice = array_slice($list, $offset, $limit, true); 94 107 return array_keys($result_slice);
+35
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
··· 31 31 private $ferretTokens = array(); 32 32 private $ferretTables = array(); 33 33 private $ferretQuery; 34 + private $ferretMetadata = array(); 34 35 35 36 protected function getPageCursors(array $page) { 36 37 return array( ··· 82 83 return $this->beforeID; 83 84 } 84 85 86 + final public function getFerretMetadata() { 87 + if (!$this->supportsFerretEngine()) { 88 + throw new Exception( 89 + pht( 90 + 'Unable to retrieve Ferret engine metadata, this class ("%s") does '. 91 + 'not support the Ferret engine.', 92 + get_class($this))); 93 + } 94 + 95 + return $this->ferretMetadata; 96 + } 97 + 85 98 protected function loadStandardPage(PhabricatorLiskDAO $table) { 86 99 $rows = $this->loadStandardPageRows($table); 87 100 return $table->loadAllFromArray($rows); ··· 111 124 $this->buildOrderClause($conn), 112 125 $this->buildLimitClause($conn)); 113 126 127 + $rows = $this->didLoadRawRows($rows); 128 + 129 + return $rows; 130 + } 131 + 132 + protected function didLoadRawRows(array $rows) { 133 + if ($this->ferretEngine) { 134 + foreach ($rows as $row) { 135 + $phid = $row['phid']; 136 + 137 + $metadata = id(new PhabricatorFerretMetadata()) 138 + ->setPHID($phid) 139 + ->setEngine($this->ferretEngine) 140 + ->setRelevance(idx($row, '_ft_rank')); 141 + 142 + $this->ferretMetadata[$phid] = $metadata; 143 + 144 + unset($row['_ft_rank']); 145 + } 146 + } 147 + 114 148 return $rows; 115 149 } 116 150 ··· 172 206 if ($this->beforeID) { 173 207 $results = array_reverse($results, $preserve_keys = true); 174 208 } 209 + 175 210 return $results; 176 211 } 177 212