用 Java 如何对 MongoDB 执行类似 SQL 的查询?

 

解决办法:esProc - Java 专业计算包

imagepng

esProc 是专门用于基于 Java 计算的类库,旨在简化 Java 代码。 SPL 是基于 esProc 计算包的脚本语言,和 Java 程序一起部署,可以理解为库外存储过程,用法和 Java 程序中调用存储过程相同,通过 JDBC 接口传递给 Java 程序执行,实现结构化计算。它非常轻巧,语法简单,类似执行 SQL 的方式,查询 MongoDB 数据。

比如,MongoDB 有名为 test1 的 collection,用来存储员工信息,Orders 字段为数组类型,用来存储当前员工的多个订单。部分数据如下:

[{
      "_id": {"$oid":   "6074f6c7e85e8d46400dc4a7"},
      "EId": 7,"State":   "Illinois","Dept": "Sales","Name":   "Alexis","Gender": "F","Salary":   9000,"Birthday": "1972-08-16",
      "Orders": [
         {"OrderID":   70,"Client": "DSG","SellerId":   7,"Amount": 288,"OrderDate": "2009-09-30"},
         {"OrderID":   131,"Client": "FOL","SellerId":   7,"Amount": 103.2,"OrderDate": "2009-12-10"}
    ]
}
{
      "_id": {"$oid":   "6074f6c7e85e8d46400dc4a8"},
      "EId": 8,"State": "California", ...
}]

用 SPL 对多层 collection 进行条件查询:


A

1

=mongo_open("mongodb://127.0.0.1:27017/mongo")

2

=mongo_shell(A1,"test1.find()")

3

=A2.conj(Orders)

4

=A3.select(Amount>1000 &&   Amount<=3000 && like@c(Client,"*s*")).fetch()

5

=mongo_close(A1)

A2可以看出来,SPL支持MongoDBjson查询表达式(findcountdistinctaggregate),比如区间查询写作:=mongo_shell(A2,"test1.find({Orders.Amount:{$gt:1000,$lt:3000}})")

上述代码可在esProc IDE中执行,存为脚本文件(比如select.dfx),通过JDBC接口在JAVA中调用,具体如下:

package Test;
  import java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.ResultSet;
  import java.sql.Statement;
  public class test1 {
      public static void main(String[]   args)throws Exception {
            Class.forName("com.esproc.jdbc.InternalDriver");
          Connection connection   =DriverManager.getConnection("jdbc:esproc:local://");
          Statement statement =   connection.createStatement();
          ResultSet result =   statement.executeQuery("call select()");

……
          if(connection != null)   connection.close();
      }
  }

与 Java 程序集成,详情参考 Java 如何调用 SPL 脚本

类似地,分组汇总代码如下:


A

1

=mongo_open("mongodb://127.0.0.1:27017/mongo")

2

=mongo_shell(A1,"test1.find()")

3

=A2.conj(Orders).groups(year(OrderDate);sum(Amount))

4

=mongo_close(A1)

关联查询代码如下:


A

1

=mongo_open("mongodb://127.0.0.1:27017/mongo")

2

=mongo_shell(A1,"test1.find()")

3

=A2.new(Orders.OrderID,Orders.Client,   Name,Gender,Dept).fetch()

4

=mongo_close(A1)

SPL 的数据结构本身就是多层的,可以直接对应多层的 collection,可以天然表达主子关系,如此一来就不必再额外进行关联。而其他计算库都是单层数据结构,难以对应多层 collection。

两个单层 collection 关联用 SPL 也很简单:


A

1

=mongo_open("mongodb://127.0.0.1:27017/mongo")

2

=mongo_shell(A1,"Orders.find()").fetch()

3

=mongo_shell(A1,"Employees.find()").fetch()

4

=mongo_close(A1)

5

=join(A2,SellerId;A3,EId)

6

=A5.new(_1.OrderID,_1.Client,_2.Name,_2.Gender,_2.Dept)

SPL表达形式多样,除了本身的过程化语法,还支持SQL语法。因为SQL数据类型不支持多层数据,所以只支持个单层collection的关联,代码如下:


A

1

=mongo_open("mongodb://127.0.0.1:27017/mongo")

2

=mongo_shell(A34,"Orders.find()").fetch()

3

=mongo_shell(A34,"Employees.find()").fetch()

4

=mongo_close(A34)

5

$select o.OrderId,o.Client,e.Name,e.Gender,e.Dept from   {A35}  o join {A36} e on   o.SellerId=e.EId

MongoDB的特色是多层数据,用json表达式计算多层数据会遇到很多困难,这种情况下用 SPL 经常可以简化计算。比如:统计下面每条记录中 incomeoutput 的数量之和。

_id

income

output

1

{"cpu":1000, "mem":500,     "mouse":"100"}

{"cpu":1000, "mem":600   ,"mouse":"120"}

2

{"cpu":2000,"mem":1000,    "mouse":"50","mainboard":500 }

{"cpu":1500, "mem":300}

json表达式计算时,代码很繁琐:

var fields = [  "income",   "output"];
db.computer.aggregate([ 
   { 
      $project:{ 
           "values":{ 
              $filter:{ 
                 input:{ 
                      "$objectToArray":"$$ROOT"
                 },
                 cond:{ 
                    $in:[ 
                       "$$this.k",
                       fields
                    ]
                 }
              }
         }
      }
   },
   { 
      $unwind:"$values"
   },
   { 
      $project:{ 
           key:"$values.k",
           values:{ 
              "$sum":{ 
                 "$let":{ 
                    "vars":{ 
                       "item":{ 
                            "$objectToArray":"$values.v"
                       }
                    },
                      "in":"$$item.v"
                 }
              }
         }
      }
   },
   {$sort: {"_id":-1}},
   { "$group": {
    "_id": "$_id",
    'income':{"$first":     "$values"},
    "output":{"$last":     "$values"}
    }},
]);

用 SPL 计算就简单多了:


A

1

=mongo_open("mongodb://127.0.0.1:27017/raqdb")

2

=mongo_shell(A1,"computer.find()").fetch()

3

=A2.new(_id:ID,income.array().sum():INCOME,output.array().sum():OUTPUT)

4

>A1.close()

说下esProc IDE的配置。在Extend library中启用MongoCli即可完成配置,配置时可用图形界面。

参考以下内容在 java 应用程序中连接 MongoDB:

从集算器外部库的文件目录,安装目录 \esProc\extlib\MongoCli,获取所需的 jar 包。 外部库的核心 jar 包是 MongoCli.jar。bson-3.6.3.jar、mongo-java-driver-3.6.3.jar 是第三方 jar 包,请根据使用的 MongoDB 版本, 从网上下载并替换为正确 jar 包。

更多 MongoDB 计算示例,参考 辅助 MongoDB 计算

更多 SPL 应用,参考 SPL 应用计算