Skip to content

Commit

Permalink
add functionality to enqueue dependent items
Browse files Browse the repository at this point in the history
  • Loading branch information
lukmzig committed Nov 14, 2024
1 parent d89462f commit 6bcbfdc
Show file tree
Hide file tree
Showing 23 changed files with 389 additions and 61 deletions.
3 changes: 3 additions & 0 deletions config/services/search/search-services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ services:
Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchResultItem\LazyLoading\AssetLazyLoadingHandlerInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchResultItem\LazyLoading\AssetLazyLoadingHandler

Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\RequiredByElementListServiceInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\RequiredByElementListService

Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchResultItem\LazyLoading\DataObjectLazyLoadingHandlerInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchResultItem\LazyLoading\DataObjectLazyLoadingHandler

Expand Down
42 changes: 42 additions & 0 deletions src/Model/SearchIndex/HitData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex;

final readonly class HitData
{
public function __construct(
private string $id,
private string $elementType,
private string $index
) {
}

public function getId(): string
{
return $this->id;
}

public function getElementType(): string
{
return $this->elementType;
}

public function getIndex(): string
{
return $this->index;
}
}
48 changes: 45 additions & 3 deletions src/Repository/IndexQueueRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
namespace Pimcore\Bundle\GenericDataIndexBundle\Repository;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Query\QueryBuilder as DBALQueryBuilder;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\QueryBuilder;
use Exception;
use Pimcore\Bundle\GenericDataIndexBundle\Entity\IndexQueue;
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;
use Pimcore\Bundle\GenericDataIndexBundle\Service\TimeServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Traits\LoggerAwareTrait;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
Expand Down Expand Up @@ -105,7 +108,7 @@ public function getUnhandledIndexQueueEntries(
/**
* @param IndexQueue[] $entries
*
* @throws \Doctrine\DBAL\Exception
* @throws DBALException
*/
public function deleteQueueEntries(array $entries): void
{
Expand Down Expand Up @@ -166,7 +169,7 @@ public function generateSelectQuery(
}

/**
* @throws \Doctrine\DBAL\Exception
* @throws DBALException
*/
public function enqueueBySelectQuery(DBALQueryBuilder $queryBuilder): void
{
Expand All @@ -186,7 +189,46 @@ public function enqueueBySelectQuery(DBALQueryBuilder $queryBuilder): void
}

/**
* @throws \Doctrine\DBAL\Exception
* @throws DBALException
* @param HitData[] $enqueueItemList
*/
public function enqueueByItemList(array $enqueueItemList, IndexQueueOperation $operation, int $operationTime): void
{
if (empty($enqueueItemList)) {
return;
}

$sql = <<<SQL
INSERT INTO
%s (elementId, elementType, elementIndexName, operation, operationTime, dispatched)
VALUES %s
ON DUPLICATE KEY
UPDATE
operation = VALUES(operation),
operationTime = VALUES(operationTime),
dispatched = VALUES(dispatched)
SQL;

$values = [];
foreach ($enqueueItemList as $item) {
$values[] = sprintf(
'(%s, %s, %s, %s, %s, 0)',
$this->connection->quote($item->getId()),
$this->connection->quote($item->getElementType()),
$this->connection->quote($item->getIndex()),
$operation->value,
$operationTime
);
}

$this->connection->executeQuery(
sprintf($sql, IndexQueue::TABLE, implode(',', $values))
);
}


/**
* @throws DBALException
*/
public function dispatchItems(
int $limit
Expand Down
4 changes: 2 additions & 2 deletions src/SearchIndexAdapter/OpenSearch/OpenSearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
*/
final class OpenSearchService implements SearchIndexServiceInterface
{
private const INDEX_VERSION_ODD = 'odd';
public const INDEX_VERSION_ODD = 'odd';

private const INDEX_VERSION_EVEN = 'even';
public const INDEX_VERSION_EVEN = 'even';

use LoggerAwareTrait;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

namespace Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\OpenSearch\Search;

use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory;
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory\SystemField;
use Pimcore\Bundle\GenericDataIndexBundle\Exception\InvalidArgumentException;
use Pimcore\Bundle\GenericDataIndexBundle\Model\OpenSearch\OpenSearchSearchInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Model\OpenSearch\Sort\FieldSort;
use Pimcore\Bundle\GenericDataIndexBundle\Model\OpenSearch\Sort\FieldSortList;
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndexAdapter\SearchResultHit;
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\SearchIndexServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\SearchIndexConfigServiceInterface;

Expand All @@ -46,6 +49,27 @@ public function fetchAllIds(OpenSearchSearchInterface $search, string $indexName
return $this->doFetchIds($search, $indexName);
}

/**
* @return HitData[]
*/
public function fetchAllTypesAndIds(
OpenSearchSearchInterface $search,
string $indexName,
bool $sortById = true
): array
{
$search = clone $search;
if ($sortById) {
$search->setSortList(new FieldSortList([new FieldSort(SystemField::ID->getPath())]));
}

if ($search->getSortList()->isEmpty()) {
throw new InvalidArgumentException('Search must have a sort defined to be able to fetch all ids');
}

return $this->doFetchIdsAndTypes($search, $indexName);
}

private function doFetchIds(OpenSearchSearchInterface $search, string $indexName, ?array $searchAfter = null): array
{
$search->setFrom(0);
Expand All @@ -63,6 +87,30 @@ private function doFetchIds(OpenSearchSearchInterface $search, string $indexName
return $ids;
}

private function doFetchIdsAndTypes(OpenSearchSearchInterface $search, string $indexName, ?array $searchAfter = null): array
{
$search->setFrom(0);
$search->setSize($this->getPageSize());
$search->setSource([SystemField::ELEMENT_TYPE->getPath()]);
$search->setSearchAfter($searchAfter);
$searchResult = $this->searchIndexService->search($search, $indexName);
$hits = $searchResult->getHits();
$idsAndTypes = array_map(
static fn (SearchResultHit $item) =>
new HitData(
id: $item->getId(),
elementType: $item->getSource()[FieldCategory::SYSTEM_FIELDS->value][SystemField::ELEMENT_TYPE->value],
index: $item->getIndex(),
),
$hits);
$lastHit = $searchResult->getLastHit();
if ($lastHit && (count($hits) === $this->getPageSize())) {
return array_merge($idsAndTypes, $this->doFetchIdsAndTypes($search, $indexName, $lastHit->getSort()));
}

return $idsAndTypes;
}

private function getPageSize(): int
{
$maxResultWindow = $this->searchIndexConfigService->getIndexSettings()['max_result_window'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@
namespace Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\OpenSearch\Search;

use Pimcore\Bundle\GenericDataIndexBundle\Model\OpenSearch\OpenSearchSearchInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;

interface FetchIdsBySearchServiceInterface
{
public function fetchAllIds(OpenSearchSearchInterface $search, string $indexName, bool $sortById = true): array;

/**
* @return HitData[]
*/
public function fetchAllTypesAndIds(
OpenSearchSearchInterface $search,
string $indexName,
bool $sortById = true
): array;
}
16 changes: 16 additions & 0 deletions src/Service/ElementService.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
use Pimcore\Bundle\GenericDataIndexBundle\Exception\InvalidElementTypeException;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\Document;
use Pimcore\Model\Element\ElementInterface;

/**
* @internal
Expand All @@ -47,6 +49,20 @@ public function getElementByType(int $id, string $type): Asset|AbstractObject|Do
};
}

/**
* @throws InvalidElementTypeException
*/
public function getElementType(ElementInterface $element): ElementType
{
return match (true) {
$element instanceof Asset => ElementType::ASSET,
$element instanceof Document => ElementType::DOCUMENT,
$element instanceof DataObject => ElementType::DATA_OBJECT,
default => throw new InvalidElementTypeException('Invalid element type: ' . $element->getType())
};
}


public function classDefinitionExists(string $name): bool
{
try {
Expand Down
7 changes: 7 additions & 0 deletions src/Service/ElementServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

namespace Pimcore\Bundle\GenericDataIndexBundle\Service;

use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
use Pimcore\Bundle\GenericDataIndexBundle\Exception\InvalidElementTypeException;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\Document;
use Pimcore\Model\Element\ElementInterface;

/**
* @internal
Expand All @@ -33,5 +35,10 @@ interface ElementServiceInterface
*/
public function getElementByType(int $id, string $type): Asset|AbstractObject|Document|null;

/**
* @throws InvalidElementTypeException
*/
public function getElementType(ElementInterface $element): ElementType;

public function classDefinitionExists(string $name): bool;
}
10 changes: 5 additions & 5 deletions src/Service/Search/SearchService/Asset/AssetSearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ public function search(
AssetSearchInterface $assetSearch,
PermissionTypes $permissionType = PermissionTypes::LIST
): AssetSearchResult {
$assetSearch = $this->searchHelper->addSearchRestrictions(
$search = $this->searchHelper->addSearchRestrictions(
search: $assetSearch,
userPermission: UserPermissionTypes::ASSETS->value,
workspaceType: AssetWorkspace::WORKSPACE_TYPE,
permissionType: $permissionType
);

$searchResult = $this->searchHelper->performSearch(
search: $assetSearch,
search: $search,
indexName: $this->assetTypeAdapter->getAliasIndexName()
);

Expand All @@ -75,12 +75,12 @@ public function search(
items: $this->searchHelper->hydrateSearchResultHits(
$searchResult,
$childrenCounts,
$assetSearch->getUser()
$search->getUser()
),
pagination: $this->paginationInfoService->getPaginationInfoFromSearchResult(
searchResult: $searchResult,
page: $assetSearch->getPage(),
pageSize: $assetSearch->getPageSize()
page: $search->getPage(),
pageSize: $search->getPageSize()
),
aggregations: $searchResult->getAggregations(),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ public function search(
DocumentSearchInterface $documentSearch,
PermissionTypes $permissionType = PermissionTypes::LIST
): DocumentSearchResult {
$documentSearch = $this->searchHelper->addSearchRestrictions(
$search = $this->searchHelper->addSearchRestrictions(
search: $documentSearch,
userPermission: UserPermissionTypes::DOCUMENTS->value,
workspaceType: DocumentWorkspace::WORKSPACE_TYPE,
permissionType: $permissionType
);

$searchResult = $this->searchHelper->performSearch(
search: $documentSearch,
search: $search,
indexName: $this->documentTypeAdapter->getAliasIndexName()
);

Expand All @@ -75,12 +75,12 @@ public function search(
items: $this->searchHelper->hydrateSearchResultHits(
$searchResult,
$childrenCounts,
$documentSearch->getUser()
$search->getUser()
),
pagination: $this->paginationInfoService->getPaginationInfoFromSearchResult(
searchResult: $searchResult,
page: $documentSearch->getPage(),
pageSize: $documentSearch->getPageSize()
page: $search->getPage(),
pageSize: $search->getPageSize()
),
aggregations: $searchResult->getAggregations(),
);
Expand Down
4 changes: 3 additions & 1 deletion src/Service/Search/SearchService/IndexNameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexService\ElementTypeAdapter\AssetTypeAdapter;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexService\ElementTypeAdapter\DataObjectTypeAdapter;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexService\ElementTypeAdapter\DocumentTypeAdapter;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\SearchIndexConfigServiceInterface;

/**
* @internal
Expand All @@ -36,6 +37,7 @@ public function __construct(
private AssetTypeAdapter $assetTypeAdapter,
private DataObjectTypeAdapter $dataObjectTypeAdapter,
private DocumentTypeAdapter $documentTypeAdapter,
private SearchIndexConfigServiceInterface $searchIndexConfigService
) {
}

Expand All @@ -56,7 +58,7 @@ public function resolveIndexName(SearchInterface $search): string
}

if ($search instanceof ElementSearch) {
return IndexName::ELEMENT_SEARCH->value;
return $this->searchIndexConfigService->getIndexName(IndexName::ELEMENT_SEARCH->value);
}

throw new InvalidArgumentException('Unsupported search type: ' . get_class($search));
Expand Down
Loading

0 comments on commit 6bcbfdc

Please sign in to comment.