mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-16 11:52:40 +01:00
96fe8c0b83
Summary: Ref T9979. This uses ngrams (specifically, trigrams) to build a reasonably efficient index for substring matching. Specifically, for a package like "Example", with ID 123, we store rows like this: ``` < ex, 123> <exa, 123> <xam, 123> <amp, 123> <mpl, 123> <ple, 123> <le , 123> ``` When the user searches for `exam`, we join this table for packages with tokens `exa` and `xam`. MySQL can do this a lot more efficiently than it can process a `LIKE "%exam%"` query against a huge table. When the user searches for a one-letter or two-letter string, we only search the beginnings of words. This is probably what they want, the only thing we can do quickly, and a reasonable/expected behavior for typeaheads. Test Plan: - Ran storage upgrades and search indexer. - Searched for stuff with "name contains". - Used typehaead and got sensible results. - Searched for `aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz` and saw only 16 joins. Reviewers: chad Reviewed By: chad Maniphest Tasks: T9979 Differential Revision: https://secure.phabricator.com/D14846
92 lines
2.1 KiB
PHP
92 lines
2.1 KiB
PHP
<?php
|
|
|
|
final class PhabricatorFulltextIndexEngineExtension
|
|
extends PhabricatorIndexEngineExtension {
|
|
|
|
const EXTENSIONKEY = 'fulltext';
|
|
|
|
public function getExtensionName() {
|
|
return pht('Fulltext Engine');
|
|
}
|
|
|
|
public function getIndexVersion($object) {
|
|
$version = array();
|
|
|
|
if ($object instanceof PhabricatorApplicationTransactionInterface) {
|
|
// If this is a normal object with transactions, we only need to
|
|
// reindex it if there are new transactions (or comment edits).
|
|
$version[] = $this->getTransactionVersion($object);
|
|
$version[] = $this->getCommentVersion($object);
|
|
}
|
|
|
|
if (!$version) {
|
|
return null;
|
|
}
|
|
|
|
return implode(':', $version);
|
|
}
|
|
|
|
public function shouldIndexObject($object) {
|
|
return ($object instanceof PhabricatorFulltextInterface);
|
|
}
|
|
|
|
public function indexObject(
|
|
PhabricatorIndexEngine $engine,
|
|
$object) {
|
|
|
|
$engine = $object->newFulltextEngine();
|
|
if (!$engine) {
|
|
return;
|
|
}
|
|
|
|
$engine->setObject($object);
|
|
|
|
$engine->buildFulltextIndexes();
|
|
}
|
|
|
|
private function getTransactionVersion($object) {
|
|
$xaction = $object->getApplicationTransactionTemplate();
|
|
|
|
$xaction_row = queryfx_one(
|
|
$xaction->establishConnection('r'),
|
|
'SELECT id FROM %T WHERE objectPHID = %s
|
|
ORDER BY id DESC LIMIT 1',
|
|
$xaction->getTableName(),
|
|
$object->getPHID());
|
|
if (!$xaction_row) {
|
|
return 'none';
|
|
}
|
|
|
|
return $xaction_row['id'];
|
|
}
|
|
|
|
private function getCommentVersion($object) {
|
|
$xaction = $object->getApplicationTransactionTemplate();
|
|
|
|
try {
|
|
$comment = $xaction->getApplicationTransactionCommentObject();
|
|
if (!$comment) {
|
|
return 'none';
|
|
}
|
|
} catch (Exception $ex) {
|
|
return 'none';
|
|
}
|
|
|
|
$comment_row = queryfx_one(
|
|
$comment->establishConnection('r'),
|
|
'SELECT c.id FROM %T x JOIN %T c
|
|
ON x.phid = c.transactionPHID
|
|
WHERE x.objectPHID = %s
|
|
ORDER BY c.id DESC LIMIT 1',
|
|
$xaction->getTableName(),
|
|
$comment->getTableName(),
|
|
$object->getPHID());
|
|
if (!$comment_row) {
|
|
return 'none';
|
|
}
|
|
|
|
return $comment_row['id'];
|
|
}
|
|
|
|
|
|
}
|