又得吐槽一下,最近开发项目,技术leader强调数据库使用mongodb作为主数据库,技术leader认为mongo完全可以代替mysql(不知道怎么想的,他mongo都没用过就下如此结论,苦逼的还是我们这些开发,至于这个leader的水分现在已经无力吐槽)
整了这么多天mongo,终于知道它不支持多表查询以及子查询。网上大多数都是迂回的一些方法,而且业务稍微复杂之后,几乎没人再用mongo做查询了,毕竟它是非关系型数据库,虽然有点关系型数据库的意思,但是术业有专攻,这不是它的强项。
好了下面说一下,基于spring data mongo这个开发,这里直接上代码以及说明,mongo的查询语句就不写了。
下面两个实体类
角色实体类
public class Role {
private String id;
private String roleName;
}
用户实体类
public class User {
private String id;
private String userName;
@DBRef
private Role role;
}
大家应该看到@DBRef这个注解了吧,就是这个,下面是重点,请仔细看:
首先user和role这两个集合必须存在于mongo数据库中,你在保存user的时候只需要设置roleid就可以了
public User contextLoads() {
User user = new User();
Role role = new Role();
role.setId("5e0416c0ac8edc3a59d9e58c");
user.setRole(role);
User entity = commonService.saveOrUpdateEntity(user);
return entity;
}
role其他字段不需要set,因为存到表里的是这样的:
它是通过id做了关联。
role集合数据是这样的,如果数据库没有role这个集合或者role集合中没有id所在的数据,那么user集合中的role字段则为空,所以如果role是内部类的话就会出现set进去为空的情况。(大家好好理解一下这句话)
接下来需要我们查询了,我们通过userId查出来的数据会自动讲role里面的数据带出来,如图:
我们知道之前设置的时候只设置了role id 但是查询的时候我们查出了其他字段,这个注解就是这个作用,这样我们就不用专门设置冗余字段了,但是问题来了,如果我们想通过roleName这个字段查出user,可以吗?
答案是不可以,因为这是单表查询,数据库只保存roleid 其他字段不存在user集合表里,因此是查不出来的,如果想要查,只能将roleName做成冗余字段,在保存的时候保存进去。
如果有这样的需求,通过角色roleid查询用户user,而且我们用户表里面已经有了roleid
我们就可以直接查询了,基于org.springframework.data.mongodb.core.MongoTemplate;的api实现查询,java代码如下:
Query query = new org.springframework.data.mongodb.core.query.Query();
query.addCriteria(Criteria.where("role.$id").is(new ObjectId("5e0416c0ac8edc3a59d9e58c")));
大家注意一下,字段名加点$符号加id,而且id的值需要new ObjectId()包裹,否则查不出来,查出来的结果和上述结果是一样的。
所以所谓的联表查询真的不适合mongo,子查询同样也是。大家就不要在折腾了,能换关系数据库就换吧。