1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-16 11:52:40 +01:00
phorge-phorge/src/applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php
epriestley 96fe8c0b83 Implement basic ngram search for Owners Package names
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
2015-12-22 08:00:33 -08:00

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'];
}
}