Skip to content

Handle Servers that Don't Support updateByQuery #384

Description

@cancan101

Some OpenSearch servers may not support updateByQuery. The only place that looks to call updateByQuery is updateIcon.

An alternative implementation of IndexIconUpdateServiceInterface that works around it looks roughly like:

<?php
declare(strict_types=1);

namespace Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DefaultSearch\DataObject;

use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory\SystemField;
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DataObject\IndexIconUpdateServiceInterface;
use Pimcore\SearchClient\SearchClientInterface;

final readonly class IndexIconUpdateServiceNoupdateByQuery implements IndexIconUpdateServiceInterface
{
    public function __construct(private SearchClientInterface $client)
    {
    }

    public function updateIcon(string $indexName, ?string $icon): void
    {
        $query = $icon === null ? $this->getQueryForNullIcon() : $this->getQueryForIconString($icon);

        // 1) start scroll
        $response = $this->client->search([
            'index' => $indexName,
            'scroll' => '1m',
            '_source' => false,
            'body' => [
                'query' => $query,
                'size' => 1000,
            ],
        ]);

        $scrollId = $response['_scroll_id'] ?? null;
        $hits = $response['hits']['hits'] ?? [];

        while ($scrollId && !empty($hits)) {
            // 2) build bulk updates
            $bulk = ['body' => []];

            foreach ($hits as $hit) {
                $id = $hit['_id'];

                $bulk['body'][] = [
                    'update' => [
                        '_index' => $indexName,
                        '_id' => $id,
                    ],
                ];
                $bulk['body'][] = [
                    'doc' => [
                        'system_fields' => [
                            'classDefinitionIcon' => $icon,
                        ],
                    ],
                ];
            }

            if (!empty($bulk['body'])) {
                $this->client->bulk($bulk);
            }

            // 3) next page
            $response = $this->client->scroll([
                'scroll_id' => $scrollId,
                'scroll' => '1m',
            ]);

            $scrollId = $response['_scroll_id'] ?? null;
            $hits = $response['hits']['hits'] ?? [];
        }

        if ($scrollId) {
            $this->client->clearScroll(['scroll_id' => $scrollId]);
        }

        // Optional: refresh index if you need immediate visibility
        // $this->client->refreshIndex(['index' => $indexName]);
    }
    
    // this code can be shared with IndexIconUpdateService
    private function getQueryForNullIcon(): array
    {
        return [
            'bool' => [
                'filter' => [
                    'exists' => ['field' => SystemField::CLASS_DEFINITION_ICON->getPath()],
                ],
            ],
        ];
    }

    // this code can be shared with IndexIconUpdateService
    private function getQueryForIconString(string $icon): array
    {
        return [
            'bool' => [
                'should' => [
                    [
                        'bool' => [
                            'must_not' => [
                                'exists' => ['field' => SystemField::CLASS_DEFINITION_ICON->getPath()],
                            ],
                        ],
                    ],
                    [
                        'bool' => [
                            'must_not' => [
                                'term' => [SystemField::CLASS_DEFINITION_ICON->getPath() => $icon],
                            ],
                        ],
                    ],
                ],
                'minimum_should_match' => 1,
            ],
        ];
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    Affected capability

    None yet

    Platform Version

    None yet

    Galaxy

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions