MongoDB的脚本操做 - Map/Reduce、Script、Group的使用

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 + "]";
    }
}

Map/Reduce 数据聚合

一、摘录了一个思路图java


Map/Reduce思路

二、 准备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);
        }
    }

执行script脚本

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操做

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
    }
}
相关文章
相关标签/搜索