MongoDB支持javascript脚本的解析。可以简化一些数据聚合、或一些脚本特殊处理。下面我们验证一下JAVA环境下调用脚本的操作。包括map/reduce操作,执行script操作,以及group的操作。
初始化数据对象
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 + "]";
}
}
Map/Reduce 数据聚合
1、摘录了一个思路图

2、 准备map.js脚本
function () {
for (var i = 0; i < this.x.length; i++) {
emit(this.x[i], 1);
}
}
3、准备reduce.js脚本
function (key, values) {
var sum = 0;
for (var i = 0; i < values.length; i++)
sum += values[i];
return sum;
}
4、执行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);
}
}
执行script脚本
MongoDB允许通过直接发送脚本或调用存储的脚本在服务器上执行JavaScript函数。
@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操作
Group操作,是相对于map/reduce的另外一种数据聚合方式。使用组操作确实有一些限制,例如在共享环境中不支持它,并且它在单个BSON对象中返回完整的结果集,因此结果应该很小,小于10,000个键。
@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());
}
结果如下:
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
}
}
网友评论