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