从零开始创建微服务-nosql-day3

5 Nosql

5.1 nosql特点

Nosql为非关系型数据库,相比于传统的关系型数据库来说,在面对高并发时候会出现一些问题,非关系型数据库对于解决高并发来说,非常有优势。MongoDB是一个基于分布式文件存储的开源数据库系统。

为什么使用nosql:

  • 对数据库高并发读写
  • 对海量数据高效率存储和访问
  • 对数据库的高扩展性和高可用性

弱点:

  • 数据库事务一致性需求
  • 数据库写实时性和读实时性需求
  • 对于复杂的sql查询,特别是多表关联查询需求

5.2 MongoDB特点

  • MongoDB是一个面向文档存储的数据库,操作起来简单便捷。
  • 你可以在MongoDB记录中设置任何属性的索引(如:FirstName=“Sameer”,Address=“8 Gandi Road”)来实现更快的排序。
  • 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
  • 如果负载的增加(需要更多的存储空间和更强的处理能力),它可以分布在计算机网络中其他节点上
  • MongoDB支持丰富的查询表达式,查询指令使用JSON形式的标记,可轻易查询数据库中的内容
  • 等等

5.3 SpringBoot集成MongoDB

5.3.1 集成简介

spring-data-mongodb,提供了MongoTemplate与 MongoRepository两种方式访问mongadb ,MongoRepository,操作简单,MongoTemplate,操作灵活,我们在项目中可以灵活适用这两种方式操作mongodb,MongoRepository的缺点是不够灵活,MongoTemplate,正好可以弥补不足。

5.3.2 搭建开发环境

  1. 引入依赖
 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-mongodb</artifactId>
 </dependency>
  1. 添加配置
spring.data.mongodb.uri=mongodb://localhost:27017/test

test为数据库名字,localhost为服务器,27017为端口号

  1. 创建对应实体类
@Data
@Document("User")
public class User {
    @Id
   public String id;
   public String name;
   public Integer age;
   public String email;
   public String creatDate;
}

@Data为lombok组件,为实体类添加set和get方法;

@Document注解是用来指定数据库的collection,这样就知道该去操作哪个collection了;

@Id为我们自动生成mongodb数据库中 _Id 。

5.4 mongoTemplate

5.4.1 新增

在实体类中set好相应的字段,直接调用save方法,调用完成后,user中的id字段会被自动填值,可以取得主键。

@SpringBootTest
class MongoApplication(){
	@Autowired
	private MongoTemplate mongoTemplate;
    //新增
    public void insertUser(User user) {
		mongoTemplate.insert(user);
	}
}

5.4.2 查询

  • 条件查询

先new一个Query,在构造方法中可以传一个Criteria,作为类似mysql的where语句,可以在后面用.and继续连接。

public void findUserList(){
    Query query = new Query(Criteria.where("name").is("tjj")).and("age").is("18");
	List<User> users = mongoTemplate.find(query, User.class);
}
  • 根据Id查询

其中xxxx为数据库中的id值

public void findId(){
	mongoTemplate.findById("xxxx",User.class)
}
  • 模糊查询

注意条件的创建过程

public void findLikeUserList(){
    String name = "tjj";
    String regex = String.format("%s%s%s","^.*",".*$");
    Pattern pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
	Query query = new Query(Criteria.where("name").regex(pattern);
    List<User> users = mongoTemplate.find(query, User.class);
}

查询可以使用排序和分页

query.with(Sort.by(Sort.Order.desc("name")));
query.skip(0);
query.limit(1);
  • 分页查询
public void findPageUserList(){
	//当前页
	int pageNo = 1;
	//每页的记录数	
	int pageSize = 3;
    String name = "tjj";
    String regex = String.format("%s%s%s","^.*",".*$");
    Pattern pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
	Query query = new Query(Criteria.where("name").regex(pattern);
    List<User> users = mongoTemplate.find(query, User.class);
    //查询记录数
    long count =  mongoTemplate.count(query,User.class);
    List<User> users = mongoTemplate.find(query,skip((pageNo-1)*pageSize).limit(pageSize),User.class);
}

5.4.3 修改

public void updateUser(User user) { 
	//根据id查询
    User user = mongoTemplate.findById("xxxx",User.class);
    //设置修改值
    user.setName("test_1");
    user.setAge(20);
    //调用方法实现修改
    Query query = new Query(Criteria.where("_id").is(user.getId()));
    Update update = new Update();
    update.set("name",user.getName());
    update.set("age",user.getAge());
    UpdateResult upsert = mongoTemplate.upsert(query,update,User.class);
    //获取修改的行数
    long modifidedCount = upsert.getModifiedCount();

}

5.4.4 删除

public void deleteUser(String id) {
	Query query = new Query(Criteria.where("_id").is("xxxx"));
    //返回的是删除的行数
	DeleteResult result = mongoTemplate.remove(query, User.class);	
}

下面重点介绍一下复杂查询,会用到Aggregate聚合查询

假设这样一个场景,MongoDB中存的json字符串含有一个数组,如

{
    "name":"小明",
    "no":"20180105",
    "test":[
        {"subject":"数学",
         "result":98
        },{"subject":"语文",
         "result":80
        },{"subject":"英语",
         "result":91
        }
    ]
},
{
    "name":"小丽",
    "no":"20180106",
    "test":[
        {"subject":"数学",
         "result":92
        },{"subject":"语文",
         "result":95
        },{"subject":"英语",
         "result":93
        }
    ]
}

这里存放的是学生的考试信息,包含姓名、学号和考试成绩,其中考试成绩是一个对象数组,包含了不同学科的考试成绩。

如果想只查询所有学生的数学成绩,用普通的查询方法,会把其他成绩也带出来,如果把数组拆开呢,这里就要使用聚合查询加上$unwind关键字。

Criteria condition = Criteria.where("test.subject").is("数学");       
Aggregation aggregationQuery = Aggregation.newAggregation(Aggregation.unwind("test"),
				Aggregation.match(condition),
				Aggregation.sort(Sort.by(Sort.Order.desc("test.result"))),
				Aggregation.skip((pageNo.longValue()-1L)*pageSize.longValue()),
				Aggregation.limit(pageSize.longValue()));
@SuppressWarnings("rawtypes")
List<Map> list = mongoTemplate.aggregate(aggregation, Test.class,Map.class).getMappedResults();

这样就可以查到每个学生的数学成绩,按照成绩倒序排序,并且使用分页。注意,这里查出来的是个Map,并不是实体类。

关于其他的关键字,网上搜索有一大堆,这里就不赘述了。

如果result成绩是用String来存储的,这时候排序字符串可能就会有问题,那该怎么解决呢

aggregationQuery = aggregationQuery.withOptions(
new AggregationOptions.Builder()
.collation(Collation.of(new Locale("zh")).
numericOrderingEnabled()).build());

5.5 mongoRepository

  1. 创建一个interface去继承MongoRepository
@Repository
public interface UserRepository extends MongonRepository<User,String>{

}
  1. 将UserRepository注入
class MongoApplicationTest{
	@Autowired
	private UserRepository userRepository;
	

}

5.5.1 添加

public void creat(){
	User user = new User();
	user.setName("tjj");
	user.setAge(18);
	userRepository.save(user);
}

5.5.2 查询

public void findId(){
	userRepository.findById("xxxx").get();
}

条件查询

public void findUserList(){
   User user = new User();
   user.setAge(18);
   user。setName("tjj");
  	Example<User> userExample = Example.of(user);
  	userRepository.findAll(userExample)
}
  

模糊查询

比条件查询多一个匹配规则

public void findLikeUserList(){
	//设置模糊查询匹配规则
	ExampleMatcher matcher = ExampleMatcher.matching()
			.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
			.withIgnoreCase(true);
    User user = new User();
	user.setAge(18);
	user.setName("t");
   	Example<User> userExample = Example.of(user,);
   	userRepository.findAll(userExample)
}

分页查询

public void findPageUserList(){
	//分页参数设置
	//0代表第一页
	Pageable pageable = PageRequest.of(0,3);
	
	User user = new User();
    user。setName("tjj");
   	Example<User> userExample = Example.of(user);
   	Page<User> pages = userRepository.findAll(userExample,pageable)
}

5.5.3 修改

修改和添加都是调用的save,自动判断是否有Id,有id就修改,无id就添加

public void updateUser(){
	User user = userRepository.findById("xxxx").get();
	user.setAge(100);
	User save = userRepository.save(user);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值