zoukankan      html  css  js  c++  java
  • spring-data-mongodb与mongo shell的对应关系

    除了特殊注释外,本文的测试结果均基于 spring-data-mongodb:1.10.6.RELEASE(spring-boot-starter:1.5.6.RELEASE),MongoDB 3.0.6


       上一章我们了解了mongo shell中aggregate复杂的互相调用关系。那么,spring-data-mongodb中aggregate又是如何与mongo交互的?是将语句拼接成我们熟悉的函数(db._collection_.find/update...)还是命令(db.runCommand)?让我们来看底层的代码到底是怎么样的。

      以下为 mongoTemplate.aggregate 方法的底层实现

        private void sendMessage(final CommandMessage message, final InternalConnection connection) {
            ByteBufferBsonOutput bsonOutput = new ByteBufferBsonOutput(connection);
            try {
                int documentPosition = message.encodeWithMetadata(bsonOutput).getFirstDocumentPosition();
                sendStartedEvent(connection, bsonOutput, message, documentPosition);
    
                connection.sendMessage(bsonOutput.getByteBuffers(), message.getId());
            } finally {
                bsonOutput.close();
            }
        }

       在往下就是字节流了,就直接看着里的数据吧,message数据为:

       test是连接的数据库名称,test.$cmd相当于db.$cmd,有过第二章的基础,这里应该明白,这个方法是走runCommand的$cmd集合的。那么相应的 mongoTemplate.getDb().command 以及 mongoTemplate.getCollection("$cmd").findOne 都可以拼接出来。

      因为这些方法需要的拼接很复杂的bson,所以这里我们引用另外一个操作符$eval。熟悉js的朋友应该都知道,eval是可以将字符串转换成方法执行的,这里我们就使用原生的aggregate语句字符串,让mongo shell去处理字符串。

      如下是五种使用$eval的方法

            //注意:命令的key:value部分,value必须被[]或者{}或者''包裹。js的字符串支持单引号和双引号两种,这里使用单引号是为了避免在java中使用大量的 
         String command = "db.user.aggregate([{$group:{_id:'$name',count:{$sum:'$age'}}}])"; BasicDBObject bson = new BasicDBObject(); bson.put("$eval",command); Object object1 = mongoTemplate.getDb().doEval(command); Object object2 = mongoTemplate.getDb().command(bson); Object object3 = mongoTemplate.getCollection("$cmd").findOne(bson); ScriptOperations operations = mongoTemplate.scriptOps(); ExecutableMongoScript script = new ExecutableMongoScript(command); Object object4 = operations.execute(script); /** * call是调用system.js集合中方法的方法,传入参数是sysytem.js表中数据的主键值, * 可在mongo shell中天插入或者使用如下代码插入。 * 插入一次后可直接使用 */ // String command = "function(){return db.user.aggregate([{$group:{_id:'$name',count:{$sum:'$age'}}}])}"; // NamedMongoScript namedMongoScript = new NamedMongoScript("user2",script); // operations.register(namedMongoScript); Object object5 = operations.call("user2");

       那么,find函数是否也如mongo shell 中,让我们继续来看看底层代码

    private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
                DbObjectCallback<T> objectCallback, String collectionName) {
            try {
                DBCursor cursor = null;
                try {
                    cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
                    if (preparer != null) {
                        cursor = preparer.prepare(cursor);
                    }
                    List<T> result = new ArrayList<T>();
                    while (cursor.hasNext()) {
                        DBObject object = cursor.next();
                        result.add(objectCallback.doWith(object));
                    }
                    return result;
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            } catch (RuntimeException e) {
                throw potentiallyConvertRuntimeException(e, exceptionTranslator);
            }
        }

      我们可以看到find也如mongo shell中一样,走的是游标的路线。

      通过上面的一系列代码的研究,我们学会了使用多种方法实现原生的aggregate,并且弄明白了aggregate在mongo shell 或者spring-data-mongodb中都存在多层的、暴露的调用方法,而find类型的请求是直接调用到了游标,这样设计的目的是什么?有兴趣的读者可以继续看看第四章 mongo中的游标与数据一致性的取舍

     


     目录

      一:spring-data-mongodb 使用原生aggregate语句

      二:mongo的runCommand与集合操作函数的关系

      三:spring-data-mongodb与mongo shell的对应关系

      四:mongo中的游标与数据一致性的取舍

  • 相关阅读:
    macbook 无声音解决方案
    webapck dev server代理请求 json截断问题
    百度卫星地图开启
    服务器 nginx配置 防止其他域名绑定自己的服务器
    记一次nginx php配置的心路历程
    遇到npm报错read ECONNRESET怎么办
    运行svn tortoiseSvn cleanup 命令失败的解决办法
    svn add 命令 递归目录下所有文件
    m4出现Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
    Ubuntu下安装GCC,mpc、mpfr、gmp
  • 原文地址:https://www.cnblogs.com/ttjsndx/p/9947370.html
Copyright © 2011-2022 走看看