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

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、摘录了一个思路图


Map/Reduce思路

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
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278

推荐阅读更多精彩内容