MongoDB支持javascript腳本的解析。能夠簡化一些數據聚合、或一些腳本特殊處理。下面咱們驗證一下JAVA環境下調用腳本的操做。包括map/reduce操做,執行script操做,以及group的操做。javascript
public static final String COLLECTION_NAME = "jmr1"; public static final String GROUP_TEST_COLLECTION = "group_test_collection"; @Autowired private MongoOperations mongoOps; @Before public void setUp(){ // 爲map/reduce操做準備數據 mongoOps.dropCollection(COLLECTION_NAME); final Jmr jmr1 = new Jmr(new String[]{"a", "b" }); final Jmr jmr2 = new Jmr(new String[]{"b", "c" }); final Jmr jmr3 = new Jmr(new String[]{"c", "d" }); mongoOps.insert(Lists.newArrayList(jmr1,jmr2,jmr3), COLLECTION_NAME); // 爲group操做準備數據 mongoOps.dropCollection(GROUP_TEST_COLLECTION); final X x1 = new X(1); final X x2 = new X(1); final X x3 = new X(2); final X x4 = new X(2); final X x5 = new X(3); final X x6 = new X(3); mongoOps.insert(Lists.newArrayList(x1,x2,x3,x4,x5,x6), GROUP_TEST_COLLECTION); } @Data @AllArgsConstructor @NoArgsConstructor class X{ int x ; } @Data class XObject { private float x; private float count; @Override public String toString() { return "XObject [x=" + x + " count = " + count + "]"; } } @Data @AllArgsConstructor @NoArgsConstructor class Jmr { String[] x; } @Data class ValueObject { private String id; private float value; @Override public String toString() { return "ValueObject [id=" + id + ", value=" + value + "]"; } }
一、摘錄了一個思路圖java
二、 準備map.js腳本服務器
function () { for (var i = 0; i < this.x.length; i++) { emit(this.x[i], 1); } }
三、準備reduce.js腳本ide
function (key, values) { var sum = 0; for (var i = 0; i < values.length; i++) sum += values[i]; return sum; }
四、執行map/reduce操做函數
/** * map/reduce,用做數據聚合。 * 腳本支持本地,或http */ @Test public void testMapReduce(){ MapReduceResults<ValueObject> results = mongoOps.mapReduce( "jmr1", "classpath:map-reduce/map.js", "classpath:map-reduce/reduce.js", ValueObject.class); for (ValueObject valueObject : results) { System.out.println(valueObject); } /** * 結果以下: * ValueObject [id=a, value=1.0] * ValueObject [id=b, value=2.0] * ValueObject [id=c, value=2.0] * ValueObject [id=d, value=1.0] */ } /** * 設置查詢條件,和輸出collection。並 map/reduce */ @Test public void testMapReduceByQueryAndOutput(){ Query query = new Query(where("x").ne(new String[] { "a", "b" })); MapReduceResults<ValueObject> results = mongoOps.mapReduce(query, "jmr1", "classpath:map-reduce/map.js", "classpath:map-reduce/reduce.js", options().outputCollection("jmr1_out"), ValueObject.class); final List<ValueObject> jmr1_out = mongoOps.findAll(ValueObject.class, "jmr1_out"); for (ValueObject valueObject : jmr1_out) { System.out.println(valueObject); } }
MongoDB容許經過直接發送腳本或調用存儲的腳本在服務器上執行JavaScript函數。this
@Test public void testScript(){ ScriptOperations scriptOps = mongoOps.scriptOps(); ExecutableMongoScript echoScript = new ExecutableMongoScript("function(x) { return x; }"); // 直接執行腳本,而不將函數存儲在服務器端。 Object directly_execute_script = scriptOps.execute(echoScript, "directly execute script"); Assert.assertEquals("directly execute script",directly_execute_script); // 使用'echo'做爲腳本的名稱來存儲腳本。給定的名稱標識腳本並容許稍後調用它。 scriptOps.register(new NamedMongoScript("echo", echoScript)); // 使用提供的參數執行名爲「echo」的腳本。 Object call = scriptOps.call("echo", "execute script via name"); Assert.assertEquals("execute script via name",call); }
Group操做,是相對於map/reduce的另一種數據聚合方式。使用組操做確實有一些限制,例如在共享環境中不支持它,而且它在單個BSON對象中返回完整的結果集,所以結果應該很小,小於10,000個鍵。spa
@Test public void testGroup(){ GroupByResults<XObject> results = mongoOps.group(GROUP_TEST_COLLECTION, // 按x分組,設置文檔值初始值{count:0} GroupBy.key("x").initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class); System.out.println(results.getRawResults().toString()); }
結果以下:code
Document { { retval = [Document { { x = 1.0, count = 2.0 } }, Document { { x = 2.0, count = 2.0 } }, Document { { x = 3.0, count = 2.0 } }], count = 6, keys = 3, ok = 1.0 } }