Skip to content

Commit b95943e

Browse files
committed
Add an example of using scripts in the scripted metrics aggs
Closes elastic#12
1 parent f5feb9e commit b95943e

File tree

8 files changed

+417
-0
lines changed

8 files changed

+417
-0
lines changed

example/stockaggs.sh

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/sh
2+
curl -s -XDELETE "http://localhost:9200/transactions"
3+
echo
4+
curl -s -XPUT "http://localhost:9200/transactions/" -d '{
5+
"settings": {
6+
"index.number_of_shards": 1,
7+
"index.number_of_replicas": 0
8+
},
9+
"mappings": {
10+
"stock": {
11+
"properties": {
12+
"type": {
13+
"type": "string",
14+
"index": "not_analyzed"
15+
},
16+
"amount": {
17+
"type": "long"
18+
}
19+
}
20+
}
21+
}
22+
}'
23+
echo
24+
curl -s -XPUT 'http://localhost:9200/transactions/stock/1' -d '{"type": "sale", "amount": 80}'
25+
curl -s -XPUT 'http://localhost:9200/transactions/stock/2' -d '{"type": "cost", "amount": 10}'
26+
curl -s -XPUT 'http://localhost:9200/transactions/stock/3' -d '{"type": "cost", "amount": 30}'
27+
curl -s -XPUT 'http://localhost:9200/transactions/stock/4' -d '{"type": "sale", "amount": 130}'
28+
29+
curl -s -XPOST "http://localhost:9200/transactions/_refresh"
30+
echo
31+
curl -s -XGET "localhost:9200/transactions/stock/_search?pretty=true" -d '{
32+
"query" : {
33+
"match_all" : {}
34+
},
35+
"aggs": {
36+
"profit": {
37+
"scripted_metric": {
38+
"init_script" : "stockaggs_init",
39+
"map_script" : "stockaggs_map",
40+
"combine_script" : "stockaggs_combine",
41+
"reduce_script" : "stockaggs_reduce",
42+
"lang": "native"
43+
}
44+
}
45+
},
46+
"size": 0
47+
}'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Integration tests for aggregation scripts
2+
#
3+
setup:
4+
- do:
5+
indices.create:
6+
index: test_index
7+
body:
8+
settings:
9+
index.number_of_shards: 1
10+
index.number_of_replicas: 0
11+
mappings.type1:
12+
properties:
13+
type: {type: string, index: not_analyzed}
14+
amount.type: long
15+
16+
- do:
17+
index: {index: transactions, type: stock, id: 1, body: {type: "sale", amount: 80}}
18+
19+
- do:
20+
index: {index: transactions, type: stock, id: 2, body: {type: "cost", amount: 10}}
21+
22+
- do:
23+
index: {index: transactions, type: stock, id: 3, body: {type: "cost", amount: 30}}
24+
25+
- do:
26+
index: {index: transactions, type: stock, id: 4, body: {type: "sale", amount: 130}}
27+
28+
- do:
29+
indices.refresh: {}
30+
31+
---
32+
33+
"Primes Test":
34+
- do:
35+
search:
36+
body:
37+
aggs:
38+
profit:
39+
scripted_metric: { "init_script" : "stockaggs_init", "map_script" : "stockaggs_map", "combine_script" : "stockaggs_combine", "reduce_script" : "stockaggs_reduce", "lang": "native"}
40+
41+
- match: { hits.total: 4}
42+
- match: { aggregations.profit.value: 170}

src/main/java/org/elasticsearch/examples/nativescript/plugin/NativeScriptExamplesPlugin.java

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
import org.elasticsearch.examples.nativescript.script.TFIDFScoreScript;
2323
import org.elasticsearch.examples.nativescript.script.PopularityScoreScriptFactory;
2424
import org.elasticsearch.examples.nativescript.script.RandomSortScriptFactory;
25+
import org.elasticsearch.examples.nativescript.script.stockaggs.CombineScriptFactory;
26+
import org.elasticsearch.examples.nativescript.script.stockaggs.InitScriptFactory;
27+
import org.elasticsearch.examples.nativescript.script.stockaggs.MapScriptFactory;
28+
import org.elasticsearch.examples.nativescript.script.stockaggs.ReduceScriptFactory;
2529
import org.elasticsearch.plugins.AbstractPlugin;
2630
import org.elasticsearch.script.ScriptModule;
2731

@@ -64,5 +68,10 @@ public void onModule(ScriptModule module) {
6468
module.registerScript(CosineSimilarityScoreScript.SCRIPT_NAME, CosineSimilarityScoreScript.Factory.class);
6569
module.registerScript(PhraseScoreScript.SCRIPT_NAME, PhraseScoreScript.Factory.class);
6670
module.registerScript(LanguageModelScoreScript.SCRIPT_NAME, LanguageModelScoreScript.Factory.class);
71+
// Scripted Metric Aggregation Scripts
72+
module.registerScript("stockaggs_init", InitScriptFactory.class);
73+
module.registerScript("stockaggs_map", MapScriptFactory.class);
74+
module.registerScript("stockaggs_combine", CombineScriptFactory.class);
75+
module.registerScript("stockaggs_reduce", ReduceScriptFactory.class);
6776
}
6877
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.elasticsearch.examples.nativescript.script.stockaggs;
16+
17+
import org.elasticsearch.common.Nullable;
18+
import org.elasticsearch.script.AbstractExecutableScript;
19+
import org.elasticsearch.script.ExecutableScript;
20+
import org.elasticsearch.script.NativeScriptFactory;
21+
22+
import java.util.ArrayList;
23+
import java.util.Map;
24+
25+
/**
26+
* Combine script from https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html
27+
* <p/>
28+
* profit = 0; for (t in _agg.transactions) { profit += t }; return profit
29+
*/
30+
public class CombineScriptFactory implements NativeScriptFactory {
31+
32+
@Override
33+
public ExecutableScript newScript(final @Nullable Map<String, Object> params) {
34+
Map<String, Object> agg = (Map<String, Object>) params.get("_agg");
35+
final ArrayList<Long> transactions = (ArrayList<Long>) agg.get(InitScriptFactory.TRANSACTIONS_FIELD);
36+
return new CombineScript(transactions);
37+
}
38+
39+
@Override
40+
public boolean needsScores() {
41+
return false;
42+
}
43+
44+
private static class CombineScript extends AbstractExecutableScript {
45+
46+
private final ArrayList<Long> transactions;
47+
48+
public CombineScript(ArrayList<Long> transactions) {
49+
this.transactions = transactions;
50+
}
51+
52+
@Override
53+
public Object run() {
54+
long profit = 0;
55+
for (long t : transactions) {
56+
profit += t;
57+
}
58+
return profit;
59+
}
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.elasticsearch.examples.nativescript.script.stockaggs;
16+
17+
import org.elasticsearch.common.Nullable;
18+
import org.elasticsearch.script.AbstractExecutableScript;
19+
import org.elasticsearch.script.ExecutableScript;
20+
import org.elasticsearch.script.NativeScriptFactory;
21+
22+
import java.util.Map;
23+
24+
import static com.google.common.collect.Lists.newArrayList;
25+
26+
/**
27+
* Init script from https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html
28+
*
29+
* _agg['transactions'] = []
30+
*/
31+
public class InitScriptFactory implements NativeScriptFactory {
32+
33+
public static final String TRANSACTIONS_FIELD = "transactions";
34+
35+
@Override
36+
public ExecutableScript newScript(final @Nullable Map<String, Object> params) {
37+
return new AbstractExecutableScript() {
38+
@Override
39+
public Object run() {
40+
((Map<String, Object>)params.get("_agg")).put(TRANSACTIONS_FIELD, newArrayList());
41+
return null;
42+
}
43+
};
44+
}
45+
46+
@Override
47+
public boolean needsScores() {
48+
return false;
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.elasticsearch.examples.nativescript.script.stockaggs;
16+
17+
import org.elasticsearch.common.Nullable;
18+
import org.elasticsearch.index.fielddata.ScriptDocValues;
19+
import org.elasticsearch.script.AbstractSearchScript;
20+
import org.elasticsearch.script.ExecutableScript;
21+
import org.elasticsearch.script.NativeScriptFactory;
22+
23+
import java.util.ArrayList;
24+
import java.util.Map;
25+
26+
/**
27+
* Map script from https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html
28+
* <p/>
29+
* if (doc['type'].value == \"sale\") { _agg.transactions.add(doc['amount'].value) } else {_agg.transactions.add(-1 * doc['amount'].value)}
30+
*/
31+
public class MapScriptFactory implements NativeScriptFactory {
32+
33+
@Override
34+
public ExecutableScript newScript(final @Nullable Map<String, Object> params) {
35+
Map<String, Object> agg = (Map<String, Object>) params.get("_agg");
36+
ArrayList<Long> transactions = (ArrayList<Long>) agg.get(InitScriptFactory.TRANSACTIONS_FIELD);
37+
return new MapScript(transactions);
38+
}
39+
40+
@Override
41+
public boolean needsScores() {
42+
return false;
43+
}
44+
45+
private static class MapScript extends AbstractSearchScript {
46+
47+
private final ArrayList<Long> transactions;
48+
49+
public MapScript(ArrayList<Long> transactions) {
50+
this.transactions = transactions;
51+
52+
}
53+
54+
@Override
55+
public Object run() {
56+
ScriptDocValues.Longs amount = (ScriptDocValues.Longs) doc().get("amount");
57+
ScriptDocValues.Strings type = (ScriptDocValues.Strings) doc().get("type");
58+
if ("sale".equals(type.getValue())) {
59+
transactions.add(amount.getValue());
60+
} else {
61+
transactions.add(-amount.getValue());
62+
}
63+
return null;
64+
}
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.elasticsearch.examples.nativescript.script.stockaggs;
16+
17+
import org.elasticsearch.common.Nullable;
18+
import org.elasticsearch.script.AbstractExecutableScript;
19+
import org.elasticsearch.script.ExecutableScript;
20+
import org.elasticsearch.script.NativeScriptFactory;
21+
22+
import java.util.ArrayList;
23+
import java.util.Map;
24+
25+
/**
26+
* Combine script from https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html
27+
* <p/>
28+
* profit = 0; for (t in _agg.transactions) { profit += t }; return profit
29+
*/
30+
public class ReduceScriptFactory implements NativeScriptFactory {
31+
32+
@Override
33+
public ExecutableScript newScript(final @Nullable Map<String, Object> params) {
34+
final ArrayList<Long> aggs = (ArrayList<Long>) params.get("_aggs");
35+
return new ReduceScript(aggs);
36+
}
37+
38+
@Override
39+
public boolean needsScores() {
40+
return false;
41+
}
42+
43+
private static class ReduceScript extends AbstractExecutableScript {
44+
45+
private final ArrayList<Long> aggs;
46+
47+
public ReduceScript(ArrayList<Long> aggs) {
48+
this.aggs = aggs;
49+
}
50+
51+
@Override
52+
public Object run() {
53+
long profit = 0;
54+
for (long t : aggs) {
55+
profit += t;
56+
}
57+
return profit;
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)