Tengo productos con etiquetas y las etiquetas están dentro de los tipos de etiquetas.

Este es un documento de muestra que agregué al índice

 {
        "_index" : "products",
        "_type" : "_doc",
        "_id" : "1219",
        "_score" : 1.0,
        "_source" : {
          "id" : "1219",
          "product_no" : "26426492261",
          "merchant_id" : 11,
          "name" : "Apple »Magic Keyboard für das 12,9\" iPad Pro (4. Generation)« iPad-Tastatur",
          "category" : "Technik>Multimedia>Zubehör>Tastatur>iPad Tastatur",
          "deep_link" : "https://foo",
          "short_description" : null,
          "long_description" : "Apple:",
          "brand" : "Apple",
          "merchant_image_url" : "http://something",
          "tagtypes" : [
            [
              {
                "Memory" : [ ]
              }
            ]
          ]
        }
      },

Ese tipo de etiqueta "Memoria" se crea dinámicamente mientras se indexan los productos.

Traté de agregar etiquetas a esa clave

 //attach tags also to ES
                        $params = [
                            'index' => 'products',
                            'id' => $product['_id'],
                            'body' => [
                                'script' => [
                                    'source' => 'if (!ctx._source.tagtypes.'.$tagType->name.'.contains(params.tag)) { ctx._source.tagtypes.'.$tagType->name.'.add(params.tag) }',
                                    'lang' => 'painless',
                                    'params' => [
                                        'tag' => $tag->value
                                    ]
                                ]
                            ]

                        ];

Pero recibo un error como

{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"failed to execute script"}],"type":"illegal_argument_exception","reason":"failed to execute script","caused_by":{"type":"script_exception","reason":"runtime error","script_stack":["if (!ctx._source.tagtypes[\"Memory\"].contains(params.tag)) { "," ^---- HERE"],"script":"if (!ctx._source.tagtypes[\"Memory\"].contains(params.tag)) { ctx._source.tagtypes[\"Memory\"].add(params.tag) }","lang":"painless","position":{"offset":16,"start":0,"end":60},"caused_by":{"type":"wrong_method_type_exception","reason":"cannot convert MethodHandle(List,int)int to (Object,String)String"}}},"status":400}

¿Alguien podría ayudarme con eso? No pude encontrar ninguna documentación al respecto, ya que los ejemplos suelen ser demasiado básicos.

¿Es generalmente posible guardar en "claves más profundas" como esta? ¿O puedo simplemente crear "etiquetas" como una lista simple (sin profundidad)

¡Gracias de antemano Adrian!

0
Adrian Gier 25 mar. 2021 a las 09:32

1 respuesta

La mejor respuesta

Su campo tagtypes es una matriz de matrices de objetos que a su vez contienen matrices de una tecla.

Cuando se trata de estructuras tan "profundas", necesitará alguna forma de iteración para actualizarlas.

Los bucles For son un buen punto de partida, pero a menudo conducen a java.util.ConcurrentModificationExceptions. Por lo tanto, es más fácil trabajar con copias temporales de datos y luego reemplazar el atributo _source correspondiente cuando haya terminado con las iteraciones:

{
  "query": {
    "match_all": {}
  },
  "script": {
    "source": """
      if (ctx._source.tagtypes == null) { return; }
      
      def originalTagtypes = ctx._source.tagtypes;
      def newTagtypes = [];
      
      for (outerGroup in originalTagtypes) {
        // keep what we've got
        newTagtypes.addAll(outerGroup);
        
        // group already present?
        def atLeastOneGroupContainsTag = outerGroup.stream().anyMatch(tagGroup -> tagGroup.containsKey(params.tag));
        
        // if not, add it as a hashmap of one single empty list
        if (!atLeastOneGroupContainsTag) {
          Map m = new HashMap();
          m.put(params.tag, []);
          newTagtypes.add(m);
        } 
      }
      
      ctx._source.tagtypes = [newTagtypes];
    """,
    "lang": "painless",
    "params": {
      "tag": "CPU"
    }
  }
}

Que terminará actualizando el tagtypes así:

{
 ...
  "tagtypes" : [
    [
      {
        "Memory" : [ ]
      },
      {
        "CPU" : [ ]        <---
      }
    ]
  ],
  ...
}

Tiene razón cuando dice que los ejemplos de documentación son demasiado básicos. Enchufe desvergonzado: Recientemente publiqué un manual que tiene como objetivo abordar exactamente eso. Encontrará muchos ejemplos de secuencias de comandos no triviales para comprender mejor el lenguaje de secuencias de comandos sin dolor.

0
Joe Sorocin 25 mar. 2021 a las 10:03