perform file search in a single query
Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
c3277095c7
commit
e576d0da68
|
@ -803,7 +803,7 @@ class Cache implements ICache {
|
|||
}
|
||||
|
||||
public function searchQuery(ISearchQuery $searchQuery) {
|
||||
return $this->querySearchHelper->searchInCaches($searchQuery, [$this]);
|
||||
return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,6 +30,7 @@ use OC\Files\Search\SearchBinaryOperator;
|
|||
use OC\SystemConfig;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\Files\Cache\ICache;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
use OCP\Files\IMimeTypeLoader;
|
||||
use OCP\Files\Search\ISearchBinaryOperator;
|
||||
use OCP\Files\Search\ISearchComparison;
|
||||
|
@ -255,9 +256,10 @@ class QuerySearchHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* @template T of array-key
|
||||
* @param ISearchQuery $searchQuery
|
||||
* @param ICache[] $caches
|
||||
* @return CacheEntry[]
|
||||
* @param array<T, ICache> $caches
|
||||
* @return array<T, ICacheEntry[]>
|
||||
*/
|
||||
public function searchInCaches(ISearchQuery $searchQuery, array $caches): array {
|
||||
// search in multiple caches at once by creating one query in the following format
|
||||
|
@ -298,9 +300,9 @@ class QuerySearchHelper {
|
|||
$query->andWhere($searchExpr);
|
||||
}
|
||||
|
||||
$storageFilters = array_map(function (ICache $cache) {
|
||||
$storageFilters = array_values(array_map(function (ICache $cache) {
|
||||
return $cache->getQueryFilterForStorage();
|
||||
}, $caches);
|
||||
}, $caches));
|
||||
$query->andWhere($this->searchOperatorToDBExpr($builder, new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters)));
|
||||
|
||||
if ($searchQuery->limitToHome() && ($this instanceof HomeCache)) {
|
||||
|
@ -326,12 +328,12 @@ class QuerySearchHelper {
|
|||
$result->closeCursor();
|
||||
|
||||
// loop trough all caches for each result to see if the result matches that storage
|
||||
$results = [];
|
||||
$results = array_fill_keys(array_keys($caches), []);
|
||||
foreach ($rawEntries as $rawEntry) {
|
||||
foreach ($caches as $cache) {
|
||||
foreach ($caches as $cacheKey => $cache) {
|
||||
$entry = $cache->getCacheEntryFromSearchResult($rawEntry);
|
||||
if ($entry) {
|
||||
$results[] = $entry;
|
||||
$results[$cacheKey][] = $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ class CacheWrapper extends Cache {
|
|||
}
|
||||
|
||||
public function searchQuery(ISearchQuery $searchQuery) {
|
||||
return $this->querySearchHelper->searchInCaches($searchQuery, [$this]);
|
||||
return current($this->querySearchHelper->searchInCaches($searchQuery, [$this]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
namespace OC\Files\Node;
|
||||
|
||||
use OC\DB\QueryBuilder\Literal;
|
||||
use OC\Files\Cache\QuerySearchHelper;
|
||||
use OC\Files\Search\SearchBinaryOperator;
|
||||
use OC\Files\Cache\Wrapper\CacheJail;
|
||||
use OC\Files\Search\SearchBinaryOperator;
|
||||
use OC\Files\Search\SearchComparison;
|
||||
use OC\Files\Search\SearchOrder;
|
||||
|
@ -253,69 +257,34 @@ class Folder extends Node implements \OCP\Files\Folder {
|
|||
$mount = $this->root->getMount($this->path);
|
||||
$storage = $mount->getStorage();
|
||||
$internalPath = $mount->getInternalPath($this->path);
|
||||
$internalPath = rtrim($internalPath, '/');
|
||||
if ($internalPath !== '') {
|
||||
$internalPath = $internalPath . '/';
|
||||
}
|
||||
|
||||
$subQueryLimit = $query->getLimit() > 0 ? $query->getLimit() + $query->getOffset() : 0;
|
||||
$rootQuery = new SearchQuery(
|
||||
new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
|
||||
new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $internalPath . '%'),
|
||||
$query->getSearchOperation(),
|
||||
]),
|
||||
$subQueryLimit,
|
||||
0,
|
||||
$query->getOrder(),
|
||||
$query->getUser()
|
||||
);
|
||||
|
||||
$files = [];
|
||||
|
||||
$cache = $storage->getCache('');
|
||||
|
||||
$results = $cache->searchQuery($rootQuery);
|
||||
foreach ($results as $result) {
|
||||
$files[] = $this->cacheEntryToFileInfo($mount, '', $internalPath, $result);
|
||||
}
|
||||
$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
|
||||
/** @var array{IMountPoint, string}[] $infoParams */
|
||||
$infoParams = [
|
||||
'' => [$mount, '']
|
||||
];
|
||||
|
||||
if (!$limitToHome) {
|
||||
$mounts = $this->root->getMountsIn($this->path);
|
||||
foreach ($mounts as $mount) {
|
||||
$subQuery = new SearchQuery(
|
||||
$query->getSearchOperation(),
|
||||
$subQueryLimit,
|
||||
0,
|
||||
$query->getOrder(),
|
||||
$query->getUser()
|
||||
);
|
||||
|
||||
$storage = $mount->getStorage();
|
||||
if ($storage) {
|
||||
$cache = $storage->getCache('');
|
||||
|
||||
$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
|
||||
$results = $cache->searchQuery($subQuery);
|
||||
foreach ($results as $result) {
|
||||
$files[] = $this->cacheEntryToFileInfo($mount, $relativeMountPoint, '', $result);
|
||||
}
|
||||
$caches[$relativeMountPoint] = $storage->getCache('');
|
||||
$infoParams[$relativeMountPoint] = [$mount, ''];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$order = $query->getOrder();
|
||||
if ($order) {
|
||||
usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
|
||||
foreach ($order as $orderField) {
|
||||
$cmp = $orderField->sortFileInfo($a, $b);
|
||||
if ($cmp !== 0) {
|
||||
return $cmp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
$files = array_values(array_slice($files, $query->getOffset(), $query->getLimit() > 0 ? $query->getLimit() : null));
|
||||
/** @var QuerySearchHelper $searchHelper */
|
||||
$searchHelper = \OC::$server->get(QuerySearchHelper::class);
|
||||
$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
|
||||
$files = array_merge(...array_map(function(array $results, $relativeMountPoint) use ($infoParams) {
|
||||
$params = $infoParams[$relativeMountPoint];
|
||||
return array_map(function(ICacheEntry $result) use ($relativeMountPoint, $params) {
|
||||
return $this->cacheEntryToFileInfo($params[0], $relativeMountPoint, $params[1], $result);
|
||||
}, $results);
|
||||
}, array_values($resultsPerCache), array_keys($resultsPerCache)));
|
||||
|
||||
return array_map(function (FileInfo $file) {
|
||||
return $this->createNode($file->getPath(), $file);
|
||||
|
|
Loading…
Reference in New Issue