Probleme mit Elasticsearch, calculatedPrices

Hallo,

ich bin gerade dabei unsere Shopware auf Elastic umzustellen. Das hat auch soweit „eigentlich“ funktioniert. Es gibt Fehler beim sw:es:index:populate, der Index wird aber trotzdem aufgebaut. Alle Shops laufen danach auch über elastic, nur in einem funktionieren die Kategorielistings nicht mehr.

Fehler bei sw:es:index:populate:

PHP Notice:  unserialize(): Error at offset 139 of 144 bytes in /data/www/shopware/engine/Shopware/Bundle/StoreFrontBundle/Gateway/DBAL/Hydrator/Hydrator.php on line 156
Offset und Bytezahl wechseln

Das ist natürlich nicht besonders aussagekräftig. Im Elasticsearch log findet sich dann folgendes:

 failed to put mappings on indices [[[sw_shop8_20180830063521/KOnqlJ7NRjiNA5H8B16dZQ]]], type [product]
java.lang.IllegalArgumentException: mapper [calculatedPrices.sani_1.rule.price] cannot be changed from type [long] to [float]
        at org.elasticsearch.index.mapper.MappedFieldType.checkTypeName(MappedFieldType.java:151) ~[elasticsearch-5.6.11.jar:5.6.11]
        at org.elasticsearch.index.mapper.MappedFieldType.checkCompatibility(MappedFieldType.java:163) ~[elasticsearch-5.6.11.jar:5.6.11]
        at org.elasticsearch.index.mapper.FieldTypeLookup.checkCompatibility(FieldTypeLookup.java:128) ~[elasticsearch-5.6.11.jar:5.6.11]
        .....
at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:210) [elasticsearch-5.6.11.jar:5.6.11]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]

 

Beim aufruf einer Kategorie im betreffenden Shop meldet das Log folgendes:

[DEBUG][o.e.a.s.TransportSearchAction] [9QxgItN] [sw_shop6_20180830063505][0], node[9QxgItNnRJKD0UpjKBAeAQ], [P], s[STARTED], a[id=nDa5WIqXSa-0YQaapd63HQ]: Failed to execute [SearchRequest{searchType=QUERY_THEN_FETCH, indices=[sw_shop6], indicesOptions=IndicesOptions[id=38, ignore_unavailable=false, allow_no_indices=true, expand_wildcards_open=true, expand_wildcards_closed=false, allow_alisases_to_multiple_indices=true, forbid_closed_indices=true], types=[product], routing='null', preference='null', requestCache=null, scroll=null, maxConcurrentShardRequests=5, batchedReduceSize=512, preFilterShardSize=128, source={
 ......
  "sort" : [
    {
      "calculatedPrices.reCH_2.calculatedPrice" : {
        "order" : "asc"
      }
    },
    {
      "id" : {
        "order" : "asc"
      }
    }
  ]
}}]
org.elasticsearch.transport.RemoteTransportException: [9QxgItN][127.0.0.1:9300][indices:data/read/search[phase/query]]
Caused by: org.elasticsearch.index.query.QueryShardException: No mapping found for [calculatedPrices.reCH_2.calculatedPrice] in order to sort on
        at org.elasticsearch.search.sort.FieldSortBuilder.build(FieldSortBuilder.java:262) ~[elasticsearch-5.6.11.jar:5.6.11]
        at org.elasticsearch.search.sort.SortBuilder.buildSort(SortBuilder.java:156) ~[elasticsearch-5.6.11.jar:5.6.11]
       .......
[?:1.8.0_181]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
[2018-08-30T06:39:12,894][DEBUG][o.e.a.s.TransportSearchAction] [9QxgItN] All shards failed for phase: [query]
org.elasticsearch.index.query.QueryShardException: No mapping found for [calculatedPrices.reCH_2.calculatedPrice] in order to sort on
        at org.elasticsearch.search.sort.FieldSortBuilder.build(FieldSortBuilder.java:262) ~[elasticsearch-5.6.11.jar:5.6.11]
        ......
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]

Relevant dürfte das hier sein : No mapping found for [calculatedPrices.reCH_2.calculatedPrice] in order to sort on

reCH ist die Kundengruppe des Shops.

Es gibt auch hier im Forum schon meherere die das Problem, oder ein sehr ähliches hatten. Allerdings verlaufen diese Threads alle im nirgendwo. 

 

Jemand eine Idee wo man hier ansetzen kann ?

 

 

Schwierig. In der Regel legt Elasticsearch das Mapping auf Basis der übertragenen Werte an. So wie sich das nun liest, wird an ersteler Stelle eine Ganzzahl übertragen, somit wird für den Key [calculatedPrices.reCH_2.calculatedPrice] anscheinend ein „long“ statt einem „float“ angelegt. Vielleicht ist hier irgendwo ein Datensatz in der Datenbank fehlerhaft? (bspw. 0€ in der s_articles_prices).

Vielleicht mal hier bei calculatedPrice im get/set explizit einen Float zurückgeben: shopware/Product.php at 5.4 · shopware/shopware · GitHub

Ob das jetzt spontan die richtige Stelle ist, kann ich nicht sagen. Danach auf jeden Fall den Index wegwerfen und einen neuen aufbauen.

 

 

Habe das long float Problem seit neuestem leider auch in einem der Subshops. Gibt’s inzwischen eine Lösung außer nur noch Preise mit Nachkommastellen?

Habe einen Pseudopreis 185.00 der bei aktuell 3 vorhandenen Produkten dazu führt das die nachfolgenden Produkte nicht angezeigt werden!
Hier gab’s mal schon ein Ticket dazu: Shopware Issuetracker

 

Neues Ticket aufmachen, die neuen Erkenntnisse hineinschreiben und auf das alte Ticket verweisen.

Wenn das jemand lösen kann, wir zahlen auch dafür!

Hast du denn mal versucht das konkret zu lösen, indem du immer einen Float übergibst? 
Wenn das die Lösung ist, kannst du das ja temporär verwenden. Hier stand ja schon ein Ansatz…

1 „Gefällt mir“

Hallo zusammen,

das Feld „calculatedPrices.sani_1.rule.price“ (und alle anderen Felder, die unter „rule“ sind) werden mit indexiert, aber aus dem Standard her nicht genutzt.
Das passiert dadurch, dass in ProductProvider::getCalculatedPrices der CheapestPrice als PriceStruct gefetched wird, dieser enthält auch die PriceRule und wird dann mit indexiert. Sortiert und gefiltert wird aber nur auf die darüberliegenden Felder „calculatedPrice“, „calculatedReferencePrice“ und „calculatedPseudoPrice“.
Somit sollte der Fehler beim Indexieren immer auftreten, wenn man z.B. Nullerwerte und normale Float-Werte in diesen Feldern hat. Trotz des Fehlers sollte man aber dennoch auch die darüberliegenden Felder sortieren bzw. filtern können.

Der Fehler beim Sortieren „No mapping found for [calculatedPrices.reCH_2.calculatedPrice] in order to sort on“ wird z.B. geschmissen, wenn man keine mögliche Währung in der Liste des Shops eingerichtet hat (ich meine nicht die Standardwährung, sondern die Auswahl der möglichen Währungen).
Zur Erklärung: Das Mapping für die „calculatedPrices“ wird dynamisch nach Kundengruppe und Währung im ProductMapping::getCalculatedPricesMapping erstellt, wenn für diesen Shop keine Währung eingerichtet ist, kann dieses Mapping auch nicht aufgebaut werden.

 

1 „Gefällt mir“

Also in der testumgebung lief nun alles vollständig. Live leider nicht. Hier ist mir heut Nachmittag elastic um die Ohren geflogen :wink:

Morgen früh starte ich den nächsten Anlauf.

Was nun alles gemacht wurde:

Alle Datenfelder mit mehr als 30.000 zeichen inhalt manuell korrigiert

Allen shops eine standardwährung zugewiesen

Preise zwangsweise in float konvertiert

Und noch was das mir gerade entfallen ist. Reiche ich morgen nach sobald alles läuft.

Danke schonmal für die ganzen Hinweise, ohne wär ich nicht so weit gekommen !

So nun noch mal die anpassungen im Detail:

feldlimit für es anpassen:

/engine/Shopware/Bunde/ESIndexingBundle/ShopIndexer.php:

private function createIndex(IndexConfiguration $configuration, ShopIndex $index)
    {
        $exist = $this->client->indices()->exists(['index' => $configuration->getName()]);
        if ($exist) {
            throw new \RuntimeException(sprintf('ElasticSearch index %s already exist.', $configuration->getName()));
        }

        $mergedSettings = [
            'settings' => [
                'number_of_shards' => $configuration->getNumberOfShards(),
                'number_of_replicas' => $configuration->getNumberOfReplicas(),
				'index.mapping.total_fields.limit' => 2000, 
            ],
        ];

        // Merge default settings with those set by plugins
        foreach ($this->settings as $setting) {
            $settings = $setting->get($index->getShop());
            if (!$settings) {
                continue;
            }

            $mergedSettings = array_replace_recursive($mergedSettings, $settings);
        }

        $this->client->indices()->create([
            'index' => $configuration->getName(),
            'body' => $mergedSettings,
        ]);
    }

/engine/Shopware/Bundle/ESIndexingBundle/Struct/Product.php

/**
     * @return Price[]
     */
    public function getCalculatedPrices()
    {
		//return $this->calculatedPrices;
        return array_map('floatval',$this->calculatedPrices);
    }

 

Da für ‘calculatedPrices.reCH_2.calculatedPrice’ (und die anderen Felder auf dieser Ebene) ein passendes ‘double’-Mapping besteht, sollte die Änderung im ProductStruct nötig sein (auch mit gemischten long und float Werten)

1 „Gefällt mir“

Mit diesen änderungen läuft nun es.

Ein weiterer Fehler der ab und zu auftritt ist folgender : 

java.lang.IllegalArgumentException: mapper [voteAverage.average] cannot be changed from type [long] to [float]

 Vorerst wie folgt gelöst:

ESIndexingBundle/Product/ProductProvider.php

public function get(Shop $shop, $numbers)
    {
        $context = $this->contextService->createShopContext(
            $shop->getId(),
            null,
            ContextService::FALLBACK_CUSTOMER_GROUP
        );

        $products = $this->productGateway->getList($numbers, $context);
        $average = $this->voteService->getAverages($products, $context);
		$average = floatval($average);

 

Damit tritt dieser Fehler aktuell nicht mehr auf. 

Mal sehen was noch so in den Logs auftritt.