Schmerzloses Elasticsearch-Skript-Tutorial (einschließlich Java-API und SpringDataElasticsearch-Aufrufskript)

1. Was ist schmerzlos

Painless ist eine Skriptsprache, die nach dem Upgrade von ElasticStack auf Version 5.0 hinzugefügt wurde und speziell das Elasticsearch-Szenario optimiert. Aufgrund der Unterstützung des statischen Typs von Java und des Lambda-Ausdrucks von Java sind Operationen mit Elasticsearch-Daten leichter und schneller, und schmerzlose Skripte sind daher einfacher und sicherer. Schmerzlose Skripte werden in Inline-Skripts (für API-Anforderungen verwendet) und gespeicherte Skripts (zur Speicherung verwendet), die SQL-Abfrageanweisungen und gespeicherten Prozeduren ähneln können, unterteilt.

Die Version von es und der Entwicklungsprozess des Skripts:
Bildbeschreibung hier einfügen
Dieser Artikel stellt nur die häufig verwendeten es-Skript-Operationsanweisungen vor, damit Sie schnell loslegen können.Wenn Sie ein tieferes Studium benötigen, ist das offizielle Dokument das beste Lernmaterial
Offizielle Dokumentenadresse:https://www.elastic.co/guide/en/elasticsearch/painless/7.9/painless-guide.html

2. Die Eigenschaften von schmerzlos

  • Schnelle Leistung: Schmerzlose Skripte werden um ein Vielfaches schneller ausgeführt als andere Skripte

  • Sicherheit: feinkörnige Zulassungsliste mit Methodenaufruf/Feldgranularität. Eine vollständige Liste der verfügbaren Klassen und Methoden finden Sie in der Painless-API-Referenz

  • Optionale Typisierung: Variablen und Parameter können explizite Typen oder dynamisch definierte Typen verwenden

  • Grammatik: Painless wird von java8 geerbt, das eine Teilmenge der erweiterten Java-Grammatik ist, um zusätzliche Skriptsprachenfunktionen bereitzustellen

  • Optimierung: speziell für Elasticsearch-Skripte entwickelt

3. Verwenden Sie kibana für Vorbereitungsvorgänge

3.1 Verwenden Sie Kibana, um Indizes und Karten zu erstellen

Wenn Sie Kibana nicht sehr gut verstehen, können Sie sich auf meinen vorherigen Artikel beziehen: Verwenden Sie Kibana, um CRUD-Operationsbefehle für Elasticsearch-Indizes zu erstellen, zu löschen und zu dokumentieren

Testindex erstellen

PUT /painless_test

Bildbeschreibung hier einfügen
Erstellen Sie eine Zuordnungsattributzuordnung

#建立mapping属性映射
PUT /painless_test/_mapping
{
    
    
  "properties": {
    
    
    "author": {
    
    
      "type": "text",
      "analyzer": "ik_max_word",
      "fields": {
    
    
        "keyword": {
    
    
          "type": "keyword"
        }
      }
    },
    "age": {
    
    
      "type": "integer"
    },
    "paperCount": {
    
    
      "type": "integer"
    },
    "coreJournal": {
    
    
      "type": "keyword"
    }
  }
}

3.2 Testdaten mit Kibana hinzufügen

PUT /painless_test/_doc/1001
{
    
    
  "author": "阿刘慈欣",
  "paperCount": [15,20,56],
  "age": 45,
  "coreJournal": [
    "MED",
    " JCR",
    " EI",
    " SCIE"
  ]
}


PUT /painless_test/_doc/1002
{
    
    
  "author": "王晋康",
  "paperCount": [23,7,32],
   "age": 63,
  "coreJournal": [
    " EI",
    " SCIE"
  ]
}

PUT /painless_test/_doc/1003
{
    
    
 "author": "周全",
 "paperCount": [57,9,34],
  "age": 18,
  "coreJournal": [
    " JCR",
    " EI"
  ]
}

4. Verwenden Sie Painless, um Abfragevorgänge durchzuführen

Hinweise zur Skriptabfrage

Die Abfrageergebnisse der Abfrage der Operation _search werden als Eingabe im Feldskript (script_fields) oder Sortierskript (sort) ausgegeben. Daher erhält die Operation im Skript den Wert über die Variable doc des Map-Typs, aber die _search-Operation ändert den Wert des Dokuments nicht, genau wie die select-Anweisung in SQL.

4.1 Feldabfrageskript

Feldabfrageoperation: Anzahl der Werke aller Autoren (Feld paperCount) addieren und abfragen

GET painless_test/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "script_fields": {
    
    
    "total_goals": {
    
    
      "script": {
    
    
        "lang": "painless",
        "inline": "int total = 0; for (int i = 0; i < doc['paperCount'].length; ++i) { total += doc['paperCount'][i]; } return total;"
      }
    }
  }
}

Die Ergebnisse der Skriptabfrage lauten wie folgt:
Bildbeschreibung hier einfügen

4.1 Skript zum Sortieren von Abfragen

Benutzerdefinierte Sortieroperation: Sortieren Sie, indem Sie den Namen und das Alter des Autors hinzufügen (nur zum Beispiel, unabhängig davon, ob es sinnvoll ist)

#排序脚本执行
POST painless_test/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
   "sort": {
    
    
    "_script": {
    
    
      "type": "string",
      "order": "desc",
      "script": {
    
    
        "lang": "painless",
        "inline": "doc['author.keyword'].value+doc['age']"
      }
    }
  }
}

Bildbeschreibung hier einfügen

5. Wie man schmerzlos verwendet, um Update-Vorgänge durchzuführen

Hinweise zur Skriptabfrage

Es wird empfohlen, die update_by_query-API für Skriptaktualisierungsoperationen zu verwenden. Diese API fragt zuerst die Datensätze ab, die die Bedingungen durch Abfrageanweisungen erfüllen (verschiedene Abfrageanweisungen können verwendet werden), und aktualisiert dann die abgefragten Datensätze gemäß den Operationen im Skript. Es ist zu beachten, dass im Vergleich zur Abfrage mit doc, um auf den Inhalt des Dokuments zuzugreifen, das Update ctx verwendet.

5.1 Feldaktualisierungsskript

Anforderungsbeschreibung : Der Wert des Felds
coreJournal“ im Originaldokument enthält Leerzeichen, und jetzt müssen die Leerzeichen entfernt werden die Werte im coreJournal um die Leerzeichen zu entfernen.

POST cqu_dev_journal_paper/_update_by_query
{
    
    
  "script": {
    
    
    "source": " for (int i = 0; i < ctx._source.coreJournal.length; i++) {   
    			ctx._source.coreJournal[i]=ctx._source.coreJournal[i].trim(); }",
    "lang": "painless"
  },
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    
          "exists": {
    
    
            "field": "coreJournal"
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  }
}

Der Ausführungseffekt ist wie folgt:
Bildbeschreibung hier einfügen

5.2 Feldaktualisierungsskript mit Parametern

Anforderungsbeschreibung : im Originaldokumentüber 30 JahrevonAutorenfelder müssen mit „Science Fiction Writer“ beginnen
Implementierungsschritte : Finden Sie zuerst gemäß der Abfragebedingung die Dokumente, deren Alter über 30 Jahre alt ist, und aktualisieren Sie dann das Autorenfeld

POST painless_test/_update_by_query
{
    
    
  "script": {
    
    
    "source": " ctx._source.author=params.prefix+ctx._source.author",
    "lang": "painless"
    , "params": {
    
    
        "prefix":"科幻作家"
    }
  },
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    
          "range": {
    
    
            "age": {
    
    
              "from": 30
            }
          }
        }
      ],
      "must_not": [],
      "should": []
    }
  }
}

Der Ausführungseffekt ist wie folgt:
Bildbeschreibung hier einfügen

6.gespeichertes Skript (Speichernutzung)

# 创建单独的脚本
POST _scripts/add-age
{
    
    
  "script": {
    
    
    "lang": "painless",
    "source": "doc['age'].value + params.myage"
  }
}

# 获取脚本
GET _scripts/add-age

# 通过指定scriptid进行调用查询
GET painless_test/_search
{
    
    
  "query": {
    
    
    "match_all": {
    
    }
  },
  "script_fields": {
    
    
    "addage": {
    
    
      "script": {
    
    
       "id": "add-age", 
        "params": {
    
    
          "myage": 15
        }
      }
    }
  }
}

# 删除脚本
DELETE _scripts/calculate-score

6. Aktualisieren Sie ES mithilfe der Java-API

Realisieren Sie die Anforderungen von Kapitel 5.1 durch die Java-API

Anforderungsbeschreibung : Der Wert des Felds
coreJournal“ im Originaldokument enthält Leerzeichen, und jetzt müssen die Leerzeichen entfernt werden die Werte im coreJournal um die Leerzeichen zu entfernen.

  public static BulkByScrollResponse updateByQuery() {
    
    
        BulkByScrollResponse bulkResponse = null;
        try {
    
    
            UpdateByQueryRequest request = new UpdateByQueryRequest("painless_test");
            request.setConflicts("proceed");
            request.setQuery(QueryBuilders.existsQuery("coreJournal"));

            String strScript = "for (int i = 0; i < ctx._source.coreJournal.length; i++) {ctx._source.coreJournal[i]=ctx._source.coreJournal[i].trim(); }"

            Script script = new Script(
                    ScriptType.INLINE, "painless",
                    strScript,
                    Collections.emptyMap());
            request.setScript(script);

            bulkResponse = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);

        } catch (IOException e) {
    
    
            log.error("ES更新异常", e.getMessage());
        }
        return bulkResponse;
    }

7. Verwenden Sie SpringDataElasticsearch, um Skripte auszuführen

Realisieren Sie die Anforderungen von Kapitel 5.1 durch SpringDataElaticsearch

Anforderungsbeschreibung : Der Wert des Felds
coreJournal“ im Originaldokument enthält Leerzeichen, und jetzt müssen die Leerzeichen entfernt werden die Werte im coreJournal um die Leerzeichen zu entfernen.

 public AjaxResult updateESScript() {
    
    
        
        int updatedCount = 0;
        try {
    
    
            //构建布尔查询语句,存在coreJournal字段的值
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.existsQuery("coreJournal"));

            NativeSearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(boolQueryBuilder)
                    .build();

            //构建查询更新语句
            UpdateQuery updateQuery = UpdateQuery.builder(query)
                    .withScriptType(ScriptType.INLINE)
                    .withScript("for (int i = 0; i < ctx._source.coreJournal.length; i++) {ctx._source.coreJournal[i]=ctx._source.coreJournal[i].trim(); }")
                    .withLang("painless")
                    .withAbortOnVersionConflict(false)
                    .build();

            /**
             * 使用ElasticsearchOperations.updateByQuery()方法执行脚本更新
             *  param: updateQuery 要执行的查询更新语句
             *  param: IndexCoordinates.of("painless_test") 获取要执行的索引
             */
            ByQueryResponse byQueryResponse = elasticsearchOperations.updateByQuery
                    (updateQuery, IndexCoordinates.of("painless_test"));

            long updated = byQueryResponse.getUpdated();
            System.out.println("本次共更新es文档数量:" + updated);

        } catch (Exception e) {
    
    
            log.info("==============es更新报错===========");
            e.printStackTrace();
            return AjaxResultGenerator.error(e.getMessage());
        }
        return AjaxResultGenerator.success(updatedCount);
    }

Supongo que te gusta

Origin blog.csdn.net/qq_29864051/article/details/130250460
Recomendado
Clasificación