Skip to content

Handle Servers that Don't Support updateByQuery #384

@cancan101

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions