Skip to main content
Version: 2026.3

Upgrade Information

Upgrade to 2026.3.3​

  • [Commands] generic-data-index:deployment:reindex has new opt-in options (--all, --assets, --dry-run, …) that also cover the folder, asset and document indices and index_settings. Without options nothing changes. See Deployment and Index Management.
  • [Indexing] A native reindex now fails if the new index cannot be created (e.g. invalid index_settings) instead of switching to an index with dynamic mapping.
  • [Indexing] New index status: IndexStatusServiceInterface reports per index whether it is complete, rebuilding (with the progress in percent), copying, degraded, incomplete or missing, with the counts it is derived from; IndexCompleteEvent fires in the messenger worker that processes the last batch of a queued full rebuild. See Index Status.
  • [Commands] generic-data-index:status shows the status of every index and the number of failed messages, and has new options: --index, --json, --check (exit code 1 while an index is not complete) and --wait (block until complete). Its leftover warning no longer lists an index whose odd/even copy is running. Without options the output and the exit code are unchanged.
  • [Indexing] A full rebuild queued by EnqueueServiceInterface (class save with a mapping change, update:index, deployment:reindex) is now marked in the settings store until its last batch is processed; the mark is what tells a rebuild from the normal lag of asynchronous indexing.
  • [Indexing] The progress of a running odd/even copy is logged every minute (documents copied so far).
  • [Database] A new migration adds an index on generic_data_index_queue.elementIndexName (the status counts the entries per index). Please make sure to execute migrations.
  • [Indexing] New methods on @internal interfaces, relevant only for custom implementations of them: SearchIndexServiceInterface::countDocuments() and getReindexTasks(), SettingsStoreServiceInterface::removeIndexState(), replaceIndexState() and removeIndexStateIfEquals(), IndexStateServiceInterface::isMappingCurrent().

Upgrade to 2026.3.2​

  • [Permissions] Searches that check a permission other than list (for example byId(), which checks view) no longer return the parent elements of a user's workspaces. As in Pimcore core, only list includes them, so the tree can show the way down to an allowed element. Requires pimcore/studio-backend-bundle 2026.3.2 or later: older versions load the folder of grids and the advanced search with byId() and return 404 for users who may only list it, for example the root folder.
  • [Permissions] Fixed: a workspace now only applies to its own path and the paths below it. Before, the permission check also applied it to any path that merely contained the workspace path (for example /Products to /Archive/Products/2024), and the search query treated a workspace such as /Products2 as lying below /Products. Effective permissions and search results for elements below such paths change accordingly.

Upgrade to 2026.3.0​

  • [Searching] Added the SearchBodyProcessorInterface extension point (tag pimcore.generic_data_index.search_body_processor, autoconfigured) to transform the serialized search body for every search and count request.
  • [Elasticsearch] Raised the minimum supported Elasticsearch server version to 8.12.2 (pimcore/elasticsearch-client ^2026.3 now requires the elasticsearch/elasticsearch client library ^8.12).
  • Added command generic-data-index:cleanup:unused-indices to delete managed indices not referenced by any alias.
  • [Searching] Element search result items now expose the relevance score via the new ScoreAwareResultItemInterface.
  • [Searching] The search result models now expose getMaxScore()

Upgrade to 2026.2.10​

  • [Commands] Added generic-data-index:snapshot:export and generic-data-index:snapshot:import. Export writes every search index into a portable, gzipped JSON-lines bundle (plus a manifest) in a configurable Flysystem storage, so a bundle can be moved between installations without a full reindex. Import recreates the local indices from the bundle and replays the documents through the bulk API; it never enqueues elements, and refuses the import (unless --force is given) when a class's mapping checksum in the manifest does not match the local class definition. Snapshots are not rotated: they accumulate in the storage until an operator deletes them. See Index snapshots for the commands and configuration.
  • [Configuration] Added the pimcore_generic_data_index.snapshot node (storage, page_size, page_bytes, bulk_size, bulk_bytes, import_workers — the import sends bulk requests through 4 worker processes by default) and a default private Flysystem storage pimcore.generic_data_index_snapshot.storage under var/generic-data-index/snapshots.
  • [Bug] generic-data-index:status (and any caller of IndexStatsService::getStats()) no longer fails with "Undefined array key aggregations" when no search index exists yet.

Upgrade to 2026.2.9​

Re-indexing required​

  • [Indexing] CalculatedValue fields are no longer always mapped as text/keyword: fields configured with element type boolean are now mapped as boolean, numeric as double and date as date (strict_date_time_no_millis). The text-based element types (input, textarea, html — including the default) keep the existing text/keyword mapping. This makes term filters, aggregations and the Studio grid filters work on typed calculated fields.
  • The mapping change is applied by bin/console generic-data-index:update:index, which recreates the affected data object indices and queues all elements for re-indexing.

Upgrade to 2026.2.8​

Re-indexing required​

  • [Indexing] Numeric, NumericRange, QuantityValue and Slider fields are no longer mapped as 32-bit float. Fields configured as integer are now mapped as long, all other ones (including Slider) as double. This prevents exact-match filters on large integers (for example customer or account IDs above 2^24) from returning neighbouring values that shared the same rounded float representation.
  • The mapping change is applied by bin/console generic-data-index:update:index, which recreates the affected data object indices and queues all elements for re-indexing.

Upgrade to 2026.1.0​

PHP and Dependency Requirements​

  • Added support for PHP 8.5.
  • Removed support for PHP 8.3 and Symfony v6.

Removed ExtJS / Admin Classic​

  • PimcoreGenericDataIndexBundle no longer implements PimcoreBundleAdminClassicInterface.
  • Removed BundleAdminClassicTrait.

Interface Changes​

  • Added optional bool $forceReload = false parameter to the byId() method on the following interfaces:
    • AssetSearchServiceInterface::byId(int $id, ?User $user = null, bool $forceReload = false)
    • DataObjectSearchServiceInterface::byId(int $id, ?User $user = null, bool $forceReload = false)
    • DocumentSearchServiceInterface::byId(int $id, ?User $user = null, bool $forceReload = false)
    • ElementSearchServiceInterface::byId(ElementType $elementType, int $id, ?User $user = null, bool $forceReload = false)
  • [Indexing] BC Break: IndexQueueRepository::generateSelectQuery() signature changed. The method now accepts an associative $columnAliases array (alias => expression) instead of the previous positional $fields array with a separate $idField parameter. Passing a numerically-indexed array will throw an InvalidArgumentException. All enqueue methods in EnqueueService and the element type adapters (AssetTypeAdapter, DocumentTypeAdapter, DataObjectTypeAdapter) have been updated accordingly. The quoteParameters() helper method has been removed.

Installer / Messenger Transport Changes​

  • The bundle installer now implements PostInstallCommandsProviderInterface. The post-install command generic-data-index:update:index -r is automatically executed during pimcore:install when using Install Profiles. Manual execution after pimcore:bundle:install is still required.
  • The messenger transport DSN is now configurable via the %pimcore.messenger.transport_dsn_prefix% container parameter (env: PIMCORE_MESSENGER_TRANSPORT_DSN_PREFIX) instead of being hardcoded to doctrine://default.

Upgrade to 2.5.9​

  • [Indexing] Moving or renaming an element with children now rewrites the children's path/fullPath in the search index for all element types: data objects are rewritten across all per-class indexes (previously only the folder index was updated, so concrete objects kept their old path after a folder move), and documents are rewritten for any parent document type (previously only moves of document folders were handled, so children of a moved/renamed page kept their old path). Stale index paths also affected path-based workspace permission filtering of search results.
  • [Configuration] BC break: the undocumented max_synchronous_children_rename_limit setting (pimcore_generic_data_index.index_service.search_settings) was removed, together with SearchIndexConfigServiceInterface::getMaxSynchronousChildrenRenameLimit() (@internal). Above that limit the children path rewrite was silently skipped and never performed by any asynchronous process, leaving the index permanently stale — the rewrite now always runs. Remove the setting from your configuration if you had set it; Symfony will otherwise fail with an "Unrecognized option" error on container build.
  • [Commands] generic-data-index:update:index now exits with a non-zero status code when one or more of its update sections (class definition, asset index, full update) fail, instead of always returning 0. All sections are still attempted and the queue is still dispatched; the command only reports the failure at the end. Deployment pipelines that treated a partial failure as success will now fail visibly — this mirrors the same change made for generic-data-index:deployment:reindex and generic-data-index:reindex in 2.5.6.
  • [Commands] Added a read-only generic-data-index:status command that reports the index queue depth (and whether items are still pending dispatch), every live index with its document count and size, and a warning for any index present in both the -even and -odd version at once (the fingerprint of an interrupted reindex).
  • [Logging] Generic Data Index now logs to a dedicated pimcore_generic_data_index Monolog channel, so its output can be filtered, raised to debug, or routed separately. Handlers without a channel restriction pick it up automatically; if you restrict a handler to an explicit channel allow-list (e.g. channels: ["pimcore"]), add pimcore_generic_data_index to that list so its records are not dropped.
  • [Logging] Failure paths (index checksum read, queue enqueue, dispatch handler) now log with structured context and the original exception, a claimed queue batch's dispatch id is logged across dispatch and processing for correlation, and the per-class mapping-checksum reindex decision (skip vs. reindex, with stored vs. current checksum) is logged.

Upgrade to 2.5.8​

  • [Indexing] The class mapping checksum is now calculated independently of the array key order, so that a changed order of e.g. the configured system languages no longer marks unchanged class definitions as changed and triggers a native reindex. Checksums stored by earlier versions are recognised and updated automatically, so upgrading by itself does not reindex existing class definitions. Only if the mapping actually changes in the same deployment as the upgrade — including a changed key order, since the previous checksum still depends on it — are the affected class definitions reindexed once, as they would have been before. From then on, order-only changes no longer trigger a reindex.
  • [Indexing] A failed native reindex no longer triggers a forced recreation of the live index. Recreation now only happens when the reindex reports that the existing documents are incompatible with the new mapping (e.g. after a field type change); genuine errors — unreachable search cluster, timeouts, rejected requests — propagate and fail the operation instead, so a transient connection failure during deployment can no longer purge the index.
  • [Indexing] Transient failures of single task-status requests during a long-running reindex are now retried instead of aborting the reindex, and an aborted reindex cancels the server-side task before cleaning up its target index.
  • [Indexing] SearchIndexServiceInterface::reindex() (@internal) now returns a ReindexResult enum instead of void.

Upgrade to 2.5.6​

  • [Commands] generic-data-index:deployment:reindex and generic-data-index:reindex now exit with a non-zero status code when reindexing fails, instead of always returning 0. Deployment pipelines executing these commands will now fail visibly on reindex errors — previously such errors were only printed while the process reported success.
  • [Indexing] Reindexing failures are no longer silently swallowed: if both the reindex and the fallback index recreation fail, the exception now propagates and the mapping checksum is not stored, so the reindex of the class definition is retried on the next run.

Upgrade to 2.5.4​

  • [Searching] The full-text search (FullTextSearch modifier) now defaults to default_operator: AND and flags: PHRASE|WHITESPACE for better relevance and to treat characters like - and . as literal text.

Upgrade to 2.5.3​

  • [Indexing] Added isReferenced field to asset index to support filtering for unreferenced assets.
  • [Indexing] Fixed: Unpublished data objects are now correctly indexed in relation fields (ManyToOne, ManyToMany, AdvancedManyToMany)

Re-indexing required​

After upgrading, execute the following command to re-index elements to include all modifications:

bin/console generic-data-index:update:index -r

Upgrade to 2.2.0​

  • [Indexing] Added id column as new primary key to generic_data_index_queue. Run migrations after updating.
  • [Searching] Added trackTotalHits parameter to DefaultSearchService and SearchExecutionService. Default value: true (always compute accurate total hits, even beyond the search engine's threshold). Set to null to use the engine's default threshold, or pass an integer for a specific limit.

Upgrade to 2.1.0​

  • Added support for Symfony 7
  • [Indexing] Added sort index for documents
  • [Indexing] Improved field collection indexing to prevent mapping conflicts when properties share a name but differ in type
  • Reindex all elements to use the new features:
    bin/console generic-data-index:update:index -r

Upgrade to 2.0.0​

  • [Indexing] Added inherited fields indicator to data object indexing
  • [Indexing] Added functionality to enqueue dependent items
  • [Indexing] Added class ID field for data object elements
  • [Indexing] Index name prefix changed from e.g. pimcore_car to pimcore_data-object_car. Old indices are not deleted automatically - delete them manually if necessary.
  • [Searching] Added ClassIdsFilter modifier to filter data objects by class ID or class name
  • Added isElementLocked() to ElementLockService for retrieving element lock status from the index
  • Reindex all elements to use the new features:
    bin/console generic-data-index:update:index -r

Breaking Changes​

  • Removed deprecated alias generic-data-index.opensearch-client. Use generic-data-index.search-client instead.
  • Replaced all deprecated OpenSearch namespace classes with DefaultSearch equivalents:
    • Pimcore\...\Model\OpenSearch → Pimcore\...\Model\DefaultSearch
    • Pimcore\...\Enum\SearchIndex\OpenSearch → Pimcore\...\Enum\SearchIndex\DefaultSearch
  • Removed deprecated class Pimcore\...\Exception\OpenSearch\SearchFailedException. Use Pimcore\...\Exception\DefaultSearch\SearchFailedException instead.
  • Removed deprecated class AsSearchModifierHandler from OpenSearch namespace. Use Pimcore\...\Attribute\Search\AsSearchModifierHandler instead.
  • Removed deprecated AbstractAdapter classes from OpenSearch namespace. Use Pimcore\...\SearchIndexAdapter\DefaultSearch\...\AbstractAdapter instead.
  • Added default data-object_ prefix to all data object class definition index names to avoid conflicts with other index names.
  • Added element type parameter to getIds method of ElementSearchResult.
  • Added getSpecialPermissions method to ElementPermissionServiceInterface for workspace language permissions.
  • Removed layout permission from DataObjectPermissions (not index-relevant).
  • Removed isLocked property from index elements (now dynamically calculated).
  • Changed workspace permissions evaluation to align with Admin Classic permission system.

Interface Changes​

  • Added PermissionTypes $permissionType parameter (default: PermissionTypes::LIST) to:
    • AssetSearchServiceInterface::search
    • DocumentSearchServiceInterface::search
    • DataObjectSearchServiceInterface::search
    • ElementSearchServiceInterface::search
  • Search service byId methods now return elements based on PermissionTypes::VIEW
  • Added type-specific interfaces:
    • AssetSearch → AssetSearchInterface
    • DocumentSearch → DocumentSearchInterface
    • ElementSearch → ElementSearchInterface
  • Search services now require type-specific search objects:
    • AssetSearchServiceInterface::search requires AssetSearchInterface
    • DocumentSearchServiceInterface::search requires DocumentSearchInterface
    • ElementSearchServiceInterface::search requires ElementSearchInterface
  • SearchProviderInterface now returns type-specific search interfaces.

Upgrade to 1.3.0​

  • [Indexing] Added Elasticsearch support alongside OpenSearch (OpenSearch remains the default). To use Elasticsearch, update your Symfony configuration:
pimcore_generic_data_index:
index_service:
client_params:
client_name: default
client_type: 'elasticsearch'
  • [Indexing] Introduced service alias generic-data-index.search-client, replacing the deprecated generic-data-index.opensearch-client (removed in 2.0). The alias provides a Pimcore\SearchClient\SearchClientInterface instance compatible with both OpenSearch and Elasticsearch.
  • OpenSearch namespace classes are deprecated. Use DefaultSearch namespace instead.
  • Reindex all elements after upgrading or switching search engines:
    bin/console generic-data-index:update:index

Upgrade to 1.1.0​

  • Reindex all elements to use the new features:
    bin/console generic-data-index:update:index