Dieser Artikel ist eine Fortsetzung von Verwenden der Elasticsearch-Java-API (BulkRequest-Registrierung). Siehe oben für Anforderungen, Datenstruktur usw.
Übrigens möchte ich mit verschiedenen in Bulk registrierten Daten umgehen.
――Ich möchte die Top 10 der täglichen Verkaufsrankings anzeigen. ――Ich möchte in der Lage sein, den Datumsbereich nach Tag, Woche, Monat usw. umzuschalten. ――Ich möchte die Anzahl der Verkaufsrankings ändern können. ――Ich möchte es nach General und Genre getrennt sehen können.
Kibana
Sie können jetzt die TOP 5 eines bestimmten Tages anzeigen.
Die obige Konfiguration kann wie folgt als Abfrage ausgedrückt werden.
GET sample-ranking-qiita-*/_search
{
"aggs": {
"range": {
"date_range": {
"field": "execDate",
"ranges": [
{
"from": "2018/01/15T00:00:00+09:00",
"to": "2018/01/15T23:59:59+09:00"
}
]
},
"aggs": {
"title_rate": {
"terms": {
"field": "title.keyword",
"size": 5,
"order": {
"sum_rate": "desc"
}
},
"aggs": {
"sum_rate": {
"sum": {
"field": "rate"
}
}
}
}
}
}
}
}
Ist es nicht ein bisschen schwer, die Verschachtelung von Aggs zu sehen? Die folgenden drei Aggs sind definiert.
rate
s mit dem Namen sum_rate
sum_rate
by title
in absteigender Reihenfolge mit dem Namen title_rate
anSQL
Als Referenz ist dies das Bild von SQL. (Ich habe es nicht ausprobiert, es tut mir leid, wenn ich einen Fehler mache.)
ranking.sql
SELECT
ranking
, title
, sum_rate
FROM (
select
ROW_NUMBER() OVER (ORDER BY sum_rate DESC) AS ranking
, tb1.title
, tb1.sum_rate
FROM (
SELECT
title
, SUM(rate) as sum_rate
FROM
tbl_ranking
WHERE
execDate >= '2018/01/15T00:00:00+09:00'
AND execDate <= '2018/01/15T23:59:59+09:00'
GROUP BY
title
) tb1
)
WHERE
ranking <= 5
Wenn ich das Ergebnis der Abfrage erhalte, ist das Ergebnis von aggs im Tag "aggregations" verschachtelt. Die Liste im Tag "Buckets" ist die Ergebnisliste für jede Aggs. Die gleichen Titel, die in Kibana angezeigt werden, sind in einer Reihe. Der Gesamtratenwert stimmt ebenfalls überein.
{
"took": 426,
"timed_out": false,
"_shards": {
"total": 15,
"successful": 15,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 24800,
"max_score": 1,
"hits": [
(Weggelassen)
]
},
"aggregations": {
"range": {
"buckets": [
{
// 3. title_Aggregierter Datumsbereich der Rate------------------------------
"key": "2018/01/14T15:00:00+0000-2018/01/15T14:59:59+0000",
"from": 1515942000000,
"from_as_string": "2018/01/14T15:00:00+0000",
"to": 1516028399000,
"to_as_string": "2018/01/15T14:59:59+0000",
"doc_count": 400,
// 2.Titel eine andere Summe_Rate absteigende Reihenfolge------------------------------
"title_rate": {
"doc_count_error_upper_bound": -1,
"sum_other_doc_count": 380,
"buckets": [
{
"key": "Neue Eröffnung",
"doc_count": 4,
"sum_rate": {
// 1.Rate insgesamt------------
"value": 355
}
},
{
"key": "Schüler",
"doc_count": 4,
"sum_rate": {
"value": 337
}
},
{
"key": "Zwischentest",
"doc_count": 4,
"sum_rate": {
"value": 333
}
},
{
"key": "Die Wahrheit des Gastgebers",
"doc_count": 4,
"sum_rate": {
"value": 292
}
},
{
"key": "Ein Moment des Spiels",
"doc_count": 4,
"sum_rate": {
"value": 292
}
}
]
}
}
]
}
}
}
Java-API
Lassen Sie uns nun die obige Abfrage mit der Java-API abrufen.
AggsSampleViewer.java
public class AggsSampleViewer {
private static Logger logger = LoggerFactory.getLogger(AggsSampleViewer.class);
//Indexformat für Jahr / Monat(yyyyMM)
private static DateTimeFormatter YM_INDEX_FORMATTER;
//Ausführungsdatum Format(yyyy/MM/dd'T'HH:mm:ss+09:00)
private static DateTimeFormatter DT_INDEX_FORMATTER;
//Verschiedene Einstellungsinformationen
QiitaSettingBean setting;
/**
*Konstrukteur
* @Informationen zur Einstellung der Parameter
*/
public AggsSampleViewer(QiitaSettingBean setting) {
super();
this.setting = setting;
DT_INDEX_FORMATTER = DateTimeFormatter.ofPattern(setting.getElasticearch().getExecDateFormat());
YM_INDEX_FORMATTER = DateTimeFormatter.ofPattern(setting.getElasticearch().getIndexYmFormat());
}
/**
*Ausführung des Akquisitionsprozesses
*
* @param subIndex Subindexname(Null zum Zeitpunkt des vollständigen Erwerbs)
* @throws Exception
*/
public void execute(String subIndex) throws Exception {
//Erstellen Sie einen Client für ELS in Java
// setting.getElasticearch().getAddress():IP Adresse
// setting.getElasticearch().getPort():Port-Nummer(Normalerweise 9300)
TransportClient client = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(setting.getElasticearch().getAddress()),
setting.getElasticearch().getPort()));
//Indexgenerierung für die Suche(Wenn ein Subindex angegeben wird, ist auch ein Subindex enthalten)
String searchIndex = setting.getElsImport().getIndex();
if (StringUtils.isNotEmpty(subIndex)) {
searchIndex = searchIndex + "-" + subIndex;
}
searchIndex += "*";
logger.debug("■■■ Suchzielindex: " + searchIndex);
// sum_Aggs for rate: Berechnen Sie den Gesamtwert der Rate
AggregationBuilder sumRateAggs = AggregationBuilders.sum("sum_rate").field("rate");
// title_Aggs for rate: Absteigende Reihenfolge der Rate nach Titel
AggregationBuilder titleRateAggs = AggregationBuilders.terms("title_rate")
//Nach Titel aggregieren
.field("title.keyword")
// setting.getRankingLimit():Ranking Nummer
.size(setting.getRankingLimit())
//Die Anzeigereihenfolge ist Summe_absteigende Reihenfolge der Rate
.order(Order.aggregation("sum_rate", false))
//zu subaggs, summe_Aggs für Rate hinzugefügt
.subAggregation(sumRateAggs)
;
//Aggs für Datumsbereich
AggregationBuilder dateRangeAggs = AggregationBuilders.dateRange("range")
//Das Ziel des Datumsbereichs ist das Ausführungsdatum der Verarbeitung
.field("execDate")
//Stellen Sie den Datumsbereich vom Tag vor 0:00 am Verarbeitungszieltag bis 0:00 am Tag ein
//Beispiel) setting.getNow(): 2018/01/16 13:20:35
// from:2018/01/15 00:00:00
// to :2018/01/16 00:00:00
.addRange(
setting.getNow().minusDays(1).truncatedTo(ChronoUnit.DAYS).format(DT_INDEX_FORMATTER)
, setting.getNow().truncatedTo(ChronoUnit.DAYS).format(DT_INDEX_FORMATTER)
)
//subaggs, Titel_Aggs für Rate hinzugefügt
.subAggregation(titleRateAggs)
;
//Ganze Abfrage
SearchRequestBuilder requestBuilder = client.prepareSearch(searchIndex)
.addAggregation(dateRangeAggs);
//Suchergebnisse abrufen
SearchResponse res = requestBuilder.get();
//Holen Sie sich das Ergebnis von Aggs der gesamten Abfrage
for (Aggregation aggs : res.getAggregations()) {
logger.debug("aggs name: "+ aggs.getName());
}
//[Aggs für Datumsbereich](Art:date_range) ----------------
InternalDateRange resDateRangeAggs = res.getAggregations().get("range");
//Überprüfen Sie den Eimer in Aggs auf Datumsbereich
for (InternalDateRange.Bucket dateRangeBucket : resDateRangeAggs.getBuckets()) {
//Schlüssel und Dokument_Die Anzahl kann mit jedem Eimer ermittelt werden
logger.debug("* resDateRangeAggs bucket key: "+ dateRangeBucket.getKey());
logger.debug("* resDateRangeAggs bucket doc_count: "+ dateRangeBucket.getDocCount());
//Von und Bis kann erhalten werden, da es sich für den Datumsbereich auf den Bucket bezieht.
logger.debug("* resDateRangeAggs bucket from: "+ dateRangeBucket.getFromAsString());
logger.debug("* resDateRangeAggs bucket to: "+ dateRangeBucket.getToAsString());
//Überprüfen Sie die Aggs-Ergebnisse in Aggs auf den Datumsbereich
for (Aggregation aggs : dateRangeBucket.getAggregations()) {
logger.debug("* resDateRangeAggs bucket aggs: "+ aggs.getName());
}
// 【title_Aggs für Rate](Art:terms) ----------------
Terms resTitleRateAggs = dateRangeBucket.getAggregations().get("title_rate");
// title_Überprüfen Sie den Eimer in Aggs auf Rate
for (Terms.Bucket termBucket : resTitleRateAggs.getBuckets()) {
logger.debug("** resTitleRateAggs bucket key: "+ termBucket.getKey());
logger.debug("** resTitleRateAggs bucket doc_count: "+ termBucket.getDocCount());
// title_Aggs Ergebnisbestätigung für Rate
for (Aggregation aggs : termBucket.getAggregations()) {
logger.debug("** resTitleRateAggs bucket aggs: "+ aggs.getName());
}
// 【sum_Aggs für Rate](Art:sum) ----------------
Sum resSumRateAggs = termBucket.getAggregations().get("sum_rate");
//Es gibt keine Aggs in Sum und Sie können Summenergebnisse erhalten
logger.debug("*** resSumRateAggs sum name: "+ resSumRateAggs.getName());
logger.debug("*** resSumRateAggs sum value: "+ resSumRateAggs.getValueAsString());
}
}
}
}
Wir werden Aggs mit derselben verschachtelten Struktur wie die Abfrage definieren. Es ist ein wenig schwierig herauszufinden, welche Aggs verwendet werden sollen und welcher Eimer zurückgegeben wird ^^; Am besten überprüfen Sie die Formel in diesem Bereich.
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-aggs.html
Die Ausführung erfolgt wie folgt.
main.java
AggsSampleViewer viewer = new AggsSampleViewer(setting);
//Generierung von Informationen zum Gesamtranking
logger.debug("■ Gesamtrangliste----------------------------------------");
viewer.execute(null);
//Shonen Ranking Informationsgenerierung
logger.debug("■ Jungenrangliste----------------------------------------");
viewer.execute("boy");
■ Gesamtrangliste----------------------------------------
■■■ Suchzielindex: sample-ranking-qiita*
aggs name: range
* resDateRangeAggs bucket key: 2018/01/14T15:00:00+0000-2018/01/15T15:00:00+0000
* resDateRangeAggs bucket doc_count: 400
* resDateRangeAggs bucket from: 2018/01/14T15:00:00+0000
* resDateRangeAggs bucket to: 2018/01/15T15:00:00+0000
* resDateRangeAggs bucket aggs: title_rate
** resTitleRateAggs bucket key:Neue Eröffnung
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 355.0
** resTitleRateAggs bucket key:Schüler
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 337.0
** resTitleRateAggs bucket key:Zwischentest
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 333.0
** resTitleRateAggs bucket key:Die Wahrheit des Gastgebers
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 292.0
** resTitleRateAggs bucket key:Ein Moment des Spiels
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 292.0
■ Jungenrangliste----------------------------------------
■■■ Suchzielindex: sample-ranking-qiita-boy*
aggs name: range
* resDateRangeAggs bucket key: 2018/01/14T15:00:00+0000-2018/01/15T15:00:00+0000
* resDateRangeAggs bucket doc_count: 141
* resDateRangeAggs bucket from: 2018/01/14T15:00:00+0000
* resDateRangeAggs bucket to: 2018/01/15T15:00:00+0000
* resDateRangeAggs bucket aggs: title_rate
** resTitleRateAggs bucket key:Schüler
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 337.0
** resTitleRateAggs bucket key:Knockout und Folge 2
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 287.0
** resTitleRateAggs bucket key:Ergebnisse vorwärts und Aussehen
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 278.0
** resTitleRateAggs bucket key:Herz
** resTitleRateAggs bucket doc_count: 4
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 267.0
** resTitleRateAggs bucket key:Meisterschaft
** resTitleRateAggs bucket doc_count: 3
** resTitleRateAggs bucket aggs: sum_rate
*** resSumRateAggs sum name: sum_rate
*** resSumRateAggs sum value: 260.0
Ich konnte die gleichen Ergebnisse wie Kibana und die Abfrage erzielen! Ah, es ist natürlich als aggregierte Abfrage, aber mit "aggs" können nur die für die Aggregation verwendeten Felder erfasst werden, und andere Felder (in diesem Fall Autoren usw. in diesem Fall) können nicht erfasst werden. Es wäre schön, wenn ich das Ergebnis der Verknüpfung mit dem Feld in "aggs" auf einmal mit "query" erhalten könnte, aber es scheint nicht so. Wenn Sie die "Größe" der "Abfrage" erhöhen, erhöht sich die Wahrscheinlichkeit, dass sie abgerufen wird, aber ich denke, dass die Obergrenze der "Größe" der "Abfrage" "10000" beträgt, sodass Sie sie definitiv in diesen Bereich bringen können. Wenn Sie sich nicht sicher sind, ist es besser, es ruhig mit einer anderen Abfrage zu bekommen.
Das Buchgenre wird als Subindex definiert, um die Einschränkung des Suchbereichs zu vereinfachen. Ich fragte mich, ob eine Verengung als Index die Belastung bei der Suche nach einem langfristigen Bereich so weit wie möglich verringern würde. Natürlich kann es in die Abfragebedingung aufgenommen werden.
AggsSampleViewer2.java
//Abfrage zur Genrefilterung
QueryBuilder queryBuilder = QueryBuilders.termQuery("index", subIndex);
//Ganze Abfrage
SearchRequestBuilder requestBuilder = client.prepareSearch(searchIndex)
.addAggregation(dateRangeAggs);
//Abfrage hinzufügen, wenn Subindex angegeben ist
if (StringUtils.isNotEmpty(subIndex)) {
requestBuilder.setQuery(queryBuilder);
}
AggsSampleViewer3.java
//
AggregationBuilder dateRangeAggs = AggregationBuilders.dateRange("range")
//
.field("execDate")
//Ändern des Datumsbereichs Wenn Sie den Datumsbereich ändern möchten, z. B. wöchentlich oder monatlich, wechseln Sie innerhalb von "addRange" zu "dateRangeAggs". Ich habe auch Informationen zur Bereichsdefinition erstellt, weil ich sie in den Einstellungen frei ändern möchte. Aggs für Datumsbereich Das Ziel des Datumsbereichs legt den Datumsbereich für das Ausführungsdatum der Verarbeitung von Von bis Bis des Suchbereichs fest.
//Beispiel)Von 10 Tagen vor dem Ausführungstermin bis Mitternacht am Ausführungstag
//"searchRange": {
// "from": "-10",
// "fromChrono": "days",
// "to": "0",
// "toChrono": "days"
//}
.addRange(
DT_INDEX_FORMATTER.format(
//Ab der Suchbereichseinstellung am Ausführungsdatum wird in Einheiten der angegebenen Einheiten hinzugefügt.
setting.getNow()
.plus(setting.getSearchRange().getFrom()
, setting.getSearchRange().findFromChronoUnit())
//Nach dem Tag abschneiden (genau um 0 Uhr machen)
.truncatedTo(ChronoUnit.DAYS))
, DT_INDEX_FORMATTER.format(
//Fügen Sie das To der Suchbereichseinstellung am Ausführungsdatum in der angegebenen Einheit hinzu
setting.getNow()
.plus(setting.getSearchRange().getTo()
, setting.getSearchRange().findToChronoUnit())
//Nach dem Tag abschneiden (genau um 0 Uhr machen)
.truncatedTo(ChronoUnit.DAYS))
)
//subaggs, Titel_Aggs für Rate hinzugefügt
.subAggregation(titleRateAggs)
;
RangeBean.java
public class RangeBean {
private int from;
private String fromChrono;
private int to;
private String toChrono;
public ChronoUnit findFromChronoUnit() {
return findChronoUnit(fromChrono);
}
public ChronoUnit findToChronoUnit() {
return findChronoUnit(toChrono);
}
/**
*Ändern Sie die Chrono-Zeichenfolge in Einheit
*
* @param chrono
* @return
*/
public ChronoUnit findChronoUnit(String chrono) {
if (StringUtils.equals(chrono, "days")) {
return ChronoUnit.DAYS;
}
if (StringUtils.equals(chrono, "weeks")) {
return ChronoUnit.WEEKS;
}
if (StringUtils.equals(chrono, "months")) {
return ChronoUnit.MONTHS;
}
if (StringUtils.equals(chrono, "years")) {
return ChronoUnit.YEARS;
}
return null;
}
//(Weggelassen)
}
Jetzt können Sie den Bereich nach Belieben festlegen, entweder monatlich oder drei Jahre.
Das nächste Mal möchte ich schreiben, wie eine Abfrage mit Java-API angegeben und abgerufen wird.