在关系型数据库中,我们设计表的时候是根据范式来设计,根据ER模型设计数据库原型等,但是Mongodb是一个无模式文档型数据库,他不能像关系型数据库一样进行语法及的关联,但是无模式也有他的好处,Mongodb可以根据对应关系将文档内联,内联的方式对于一对一或者一对多的关系是非常有效的,但是到了多对多表现的其实就是非常不完美了,如果一个劲的内联其实也可以解决问题,但是如果一个文档的数据量太多,超过了18M也是问题,所以文档关联的非常重要的,所以Mongodb也知道了这个问题,他们提供了一个$lookup,这个操作时放在聚合函数中的,所以说这个操作的重要性还是很明显的,为什么这么说呢?因为目前的Mongodb的主要操作分为两大类,第一大类是基于单个集合的增删改查,另一大类就是聚合,对于单一集合的操作对我们来说基本不存在什么问题,只要是对业务个固定场景设计好即可,但是针对聚合操作我们可以做的就很多了,这里的聚合有点像关系型数据库的groupby但是还有很多其他的功能,比如我们今天要说的关联查询,$loopkup有4个参数,分别是:from,localField,foreignField和as,具体每个字段的含义我先不说,先上一段代码,这段代码是基于spring-data-mongodb的实现。
@RequestMapping("getlookupOp")
@ResponseBody
public Map<String, Object> getlookupOp() {
Map<String, Object> msg = Maps.newHashMap();
LookupOperation op = LookupOperation.newLookup().from("user_info").localField("departId").foreignField("no")
.as("userList");
ProjectionOperation project = Aggregation.project("departId")
.and("departName").as("departName")
.and("userList.username").as("userId")
.and("userList.no").as("deptNo")
.and("userList.indate").as("inDate")
.and("userList.age").as("userAge")
.and("userList.address").as("userAddress");
Aggregation aggregation = Aggregation.newAggregation(op,project);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "department_info", Document.class);
msg.put("msg", results.getMappedResults());
return msg;
}
这个里面我设计了两个文档,分别是:
{
"_id" : ObjectId("5beccb64b3fadf1904674e99"),
"departId" : "11",
"departName" : "datacenter"
}
{
"_id" : ObjectId("5b908750dac78d1a5cb62dd7"),
"username" : "whthomas",
"no" : "11",
"indate" : ISODate("2018-11-14T12:12:12.000Z"),
"age" : "21",
"address" : {
"city" : "shenyang",
"zone" : "heping"
}
}
我们想要操作的目的是对结果进行关联,关联字段是departId和no,让后将关联后取到的user_info表数据内联到表中。对应的关系型数据库的操作是:
select department_info.*,user_info.* as userList from department_info left join user_info on department_info.departId=user_info.no
是不是一下就明白了,Mongodb可以做的事情还是很多的,还有很多是我们可以挖掘的,努力吧。