Mam produkty z tagami, a znaczniki są wewnątrz tagtypes.

Jest to przykładowy dokument, który dodałem do indeksu

 {
        "_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" : [ ]
              }
            ]
          ]
        }
      },

Że tagtype "pamięć" jest dynamicznie tworzony podczas indeksowania produktów.

Próbowałem dodać tagi do tego klucza

 //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
                                    ]
                                ]
                            ]

                        ];

Ale otrzymuję błąd

{"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}

Czy ktoś mógłby mi z tym pomóc. Nie mogłem znaleźć żadnej dokumentacji na ten temat, ponieważ przykłady są często zbyt podstawowe.

Czy na ogół jest możliwe zapisanie w "głębszych kluczach" w ten sposób? Lub czy mogę po prostu utworzyć "Tagi" jako prosta lista (bez żadnej głębokości)

Dziękuję z góry Adriana!

0
Adrian Gier 25 marzec 2021, 09:32

1 odpowiedź

Najlepsza odpowiedź

Twoje pole tagtypes jest tablicą tablic obiektów, które pojawiają się same tablice jednokierunkowe.

Kiedy masz do czynienia z takimi "głębokim" strukturami, potrzebujesz niektóre formę iteracji, aby je zaktualizować.

For pętle są dobrym miejscem, ale często prowadzą do java.util.ConcurrentModificationExceptions. Więc łatwiej jest pracować z tymczasowymi kopiami danych, a następnie zastąpić odpowiedni atrybut _source podczas wykonywania z iteracjami:

{
  "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"
    }
  }
}

Który skończy się aktualizować tagtypes jak więc:

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

Masz rację, gdy mówisz, że przykłady dokumentacji są zbyt podstawowe. Bezwstydna wtyczka: Niedawno Opublikowano podręcznik, który ma na celu dokładnie taki. Znajdziesz wiele innych niż trywialne przykłady skryptów, aby uzyskać lepsze zrozumienie bezbolesnego języka skryptowego.

0
Joe Sorocin 25 marzec 2021, 10:03