MongoDB入门使用

1. 什么是MongoDB

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
MongoDB 支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。

1.1 MongoDB与Mysql区别

1.2 MongoDB的使用场景

参考:https://mongoing.com/archives/3609

  • 案例1
    用在应用服务器的日志记录,查找起来比文本灵活,导出也很方便。也是给应用练手,从外围系统开始使用MongoDB。
    用在一些第三方信息的获取或者抓取,因为MongoDB的schema-less,所有格式灵活,不用为了各种格式不一样的信息专门设计统一的格式,极大得减少开发的工作。

  • 案例2
    mongodb之前有用过,主要用来存储一些监控数据,No schema 对开发人员来说,真的很方便,增加字段不用改表结构,而且学习成本极低。

  • 案例3
    使用MongoDB做了O2O快递应用,·将送快递骑手、快递商家的信息(包含位置信息)存储在 MongoDB,然后通过 MongoDB 的地理位置查询,这样很方便的实现了查找附近的商家、骑手等功能,使得快递骑手能就近接单,目前在使用MongoDB 上没遇到啥大的问题,官网的文档比较详细,很给力。

经常跟一些同学讨论 MongoDB 业务场景时,会听到类似『你这个场景 mysql 也能解决,没必要一定用 MongoDB』的声音,的确,并没有某个业务场景必须要使用 MongoDB才能解决,但使用 MongoDB 通常能让你以更低的成本解决问题(包括学习、开发、运维等成本),下面是 MongoDB 的主要特性,大家可以对照自己的业务需求看看,匹配的越多,用 MongoDB 就越合适。

从目前阿里云 MongoDB 云数据库上的用户看,MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例:

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
  • 视频直播,使用 MongoDB 存储用户信息、礼物信息等
  • ……

如果你还在为是否应该使用 MongoDB,不如来做几个选择题来辅助决策(注:以下内容改编自 MongoDB 公司 TJ 同学的某次公开技术分享)。
如果以下有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择 MongoDB 绝不会后悔。




2. MongoDB概念解析

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持多表连接
primary key primary key 主键,MongoDB自动将_id字段设置为主键

2.1 数据库【一个mongodb中可以建立多个数据库】

1、 Help查看命令提示 
db.help();
2、 切换/创建数据库
use test
如果数据库不存在,则创建数据库,否则切换到指定数据库
3、 查询所有数据库 
show dbs;
4、 删除当前使用数据库 
db.dropDatabase();
5、 查看当前使用的数据库 
db.getName();
6、 显示当前db状态 
db.stats();
7、 当前db版本 
db.version();
8、 查看当前db的链接机器地址 
db.getMongo();

2.2 文档【文档是一组键值(key-value)对,即(BSON)】

2.3 集合【集合就相当于Mysql中的一张表】

集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

1、 创建一个集合(table)
db.createCollection( "collName");
2、 得到指定名称的集合(table )
db.getCollection("user");

2.4 支持的数据类型

数据类型 描述
String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Arrays 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。


3. MongoDB入门

3.1 Insert


插入后自动帮我们创建了id,创建id的类型为Objectld【默认】
Objectld使用12字节的存储空间,每个字节二位十六进制数字, 是一个24位的字符串

  • 时间戳:时间不断变化的
  • 机器:主机的唯_标识码。通常是机器主机名的散列值,这样可以确保不同主机 生成不同的Objectld ,不产生冲突。
  • PID:为了确保在同一台机器上并发的多个进程产生的Objectld是唯一的,所以加上进程标识符(PID).
  • 计数器:前9个字节保证了同一秒钟不同机器不同进程产生的Objectld是唯一的。 后3个字节就是一个自动增加的计数器,确保相同进程同一秒产生的Objectld也是不一样。同一秒最多允许每个进程拥有IS 777 2托个不同的Objectld。

3.2 Query

3.2.1 where
# select * from User where name = 'zhangsan'

> db.User.find({name:"zhangsan"})
3.2.2 fields【指定列】
# select name, age from User where age = 21

> db.User.find({age:21}, {'name':1, 'age':1})
3.2.3 sort
# select * from User order by age

> db.User.find().sort({age:1})

//sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式.
//其中 1 为升序排列,而 -1 是用于降序排列。
3.2.4 in
# select * from User where age in (21, 26, 32)

> db.User.find({age:{$in:[21,26,32]}})
3.2.5 count
# select count(*) from User where age >20

> db.User.find({age:{$gt:20}}).count()
3.2.6 or
# select * from User where age = 21 or age = 28

> db.User.find({$or:[{age:21}, {age:28}]})
3.2.7 limit
# select * from User skip 2 limit 3

> db.User.find().skip(0).limit(3)

//在 MongoDB 中使用 limit()方法来读取指定数量的数据,skip()方法来跳过指定数量的数据。

3.3 Update

# update Userset age = 100, sex = 0 where name = 'user1'

> db.User.update({name:"zhangsan"}, {$set:{age:100, sex:0}})

Update()有几个参数需要注意。
  db.collection.update(criteria, objNew, upsert, mult)

    criteria:需要更新的条件表达式
    objNew:更新表达式
    upsert:如FI标记录不存在,是否插入新文档。 
    multi:是否更新多个文档。

3.4 Remove

> db.User.remove(id)
//移除对应id的行

> db.User.remove({})
//移除所有

3.5 聚合操作

3.6 索引

>db.User.createIndex({"name":1})

//name值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可


4. SpringBoot集成MongoDB

spring-data-mongodb提供了MongoTemplate与MongoRepository两种方式:
方式一:MongoRepository 操作简单
方式二:MongoTemplate 操作灵活

4.1 添加依赖

<dependency>
     <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

4.2 添加配置

spring.data.mongodb.uri=mongodb://47.93.118.241:27017/test

4.3 添加实体

@Data
@Document("User")
public class User {

 @Id
 private String id;
 private String name;
 private Integer age;
 private String email;
 private String createDate;
}

4.4 基于MongoTemplate开发CRUD

mongoTemplate常用方法:

    mongoTemplate.findAll(User.class): 查询User文档的全部数据
    mongoTemplate.findById(<id>, User.class): 查询User文档id为id的数据
    mongoTemplate.find(query, User.class);: 根据query内的查询条件查询
    mongoTemplate.upsert(query, update, User.class): 修改
    mongoTemplate.remove(query, User.class): 删除
    mongoTemplate.insert(User): 新增

    Query对象
      1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)  
      2、精准条件:criteria.and(“key”).is(“条件”)     模糊条件:criteria.and(“key”).regex(“条件”)
      3、封装条件:query.addCriteria(criteria)
      4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
      5、Query.addCriteria(new Criteria().andOperator(gt,lt));
      6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
      7、排序 :query.with(new Sort(Sort.Direction.ASC, "age"). and(new Sort(Sort.Direction.DESC, "date")))
@SpringBootTest
class DemomogoApplicationTests {
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	//添加
	@Test
	public void createUser() {
		User user = new User();
		user.setAge(20);
		user.setName("test");
		user.setEmail("4932200@qq.com");
		User user1 = mongoTemplate.insert(user);
		System.out.println(user1);
	}
	
	//查询所有
	@Test
	public void findUser() {
		List<User> userList = mongoTemplate.findAll(User.class);
		System.out.println(userList);
	}
	
	//根据id查询
	@Test
	public void getById() {
		User user =
			mongoTemplate.findById("5ffbfa2ac290f356edf9b5aa", User.class);
		System.out.println(user);
	}
	
	//条件查询
	@Test
	public void findUserList() {
		Query query = new Query(Criteria.where("name").is("test").and("age").is(20));
		List<User> userList = mongoTemplate.find(query, User.class);
		System.out.println(userList);
	}
	
	//模糊查询
	@Test
	public void findUsersLikeName() {
		String name = "est";
		String regex = String.format("%s%s%s", "^.*", name, ".*$");
		Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		Query query = new Query(Criteria.where("name").regex(pattern));
		List<User> userList = mongoTemplate.find(query, User.class);
		System.out.println(userList);
	}
	
	//分页查询
	@Test
	public void findUsersPage() {
		String name = "est";
		int pageNo = 1;
		int pageSize = 10;
		
		Query query = new Query();
		String regex = String.format("%s%s%s", "^.*", name, ".*$");
		Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		query.addCriteria(Criteria.where("name").regex(pattern));

                // 记录数
		int totalCount = (int) mongoTemplate.count(query, User.class);
                // 分页
		List<User> userList = mongoTemplate.find(query.skip((pageNo - 1) * pageSize).limit(pageSize), User.class);
		
		Map<String, Object> pageMap = new HashMap<>();
		pageMap.put("list", userList);
		pageMap.put("totalCount", totalCount);
		System.out.println(pageMap);
	}
	
	//修改
	@Test
	public void updateUser() {
		User user = mongoTemplate.findById("5ffbfa2ac290f356edf9b5aa", User.class);
		user.setName("test_1");
		user.setAge(25);
		user.setEmail("493220990@qq.com");
		Query query = new Query(Criteria.where("_id").is(user.getId()));
		Update update = new Update();
		update.set("name", user.getName());
		update.set("age", user.getAge());
		update.set("email", user.getEmail());
		UpdateResult result = mongoTemplate.upsert(query, update, User.class);
		long count = result.getModifiedCount();
		System.out.println(count);
	}
	
	//删除操作
	@Test
	public void delete() {
		Query query =
			new Query(Criteria.where("_id").is("5ffbfa2ac290f356edf9b5aa"));
		DeleteResult result = mongoTemplate.remove(query, User.class);
		long count = result.getDeletedCount();
		System.out.println(count);
	}
}

4.5 基于MongoRepository开发CRUD

★★★★★★★★★Spring Data提供了对mongodb数据访问的支持,我们只需要继承MongoRepository类,按照Spring Data规范就可以了★★★★★★★★★★

//添加Repository接口继承MongoRepository    因为MongoRepository 帮我们实现了对MongoDB的操作方法。
@Repository
public interface UserRepository extends MongoRepository<User, String> {

}



//开发CRUD
@SpringBootTest
class DemomogoApplicationTests1 {

    @Autowired
    private UserRepository userRepository;

    //添加
    @Test
    public void createUser() {
        User user = new User();
        user.setAge(20);
        user.setName("张三");
        user.setEmail("3332200@qq.com");
        User user1 = userRepository.save(user);   // 返回的user里面有新增的user的id
    }

    //查询所有
    @Test
    public void findUser() {
        List<User> userList = userRepository.findAll();
        System.out.println(userList);
    }

    //id查询
    @Test
    public void getById() {
        User user = userRepository.findById("5ffbfe8197f24a07007bd6ce").get();
        System.out.println(user);
    }

    //条件查询
    @Test
    public void findUserList() {
        User user = new User();
        user.setName("张三");
        user.setAge(20);

        Example<User> userExample = Example.of(user);
        List<User> userList = userRepository.findAll(userExample);
        System.out.println(userList);
    }

    //模糊查询
    @Test
    public void findUsersLikeName() {
        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
                .withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写

        User user = new User();
        user.setName("三");

        Example<User> userExample = Example.of(user, matcher);
        List<User> userList = userRepository.findAll(userExample);
        System.out.println(userList);
    }

    //分页查询
    @Test
    public void findUsersPage() {

        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询
                .withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写

        User user = new User();
        user.setName("三");
        Example<User> userExample = Example.of(user, matcher);

        Sort sort = Sort.by(Sort.Direction.DESC, "age");
        //0为第一页
        Pageable pageable = PageRequest.of(0, 10, sort);


        //创建实例
        Example<User> example = Example.of(user, matcher);
        Page<User> pages = userRepository.findAll(example, pageable);
        System.out.println(pages);
    }

    //修改
    @Test
    public void updateUser() {
        User user = userRepository.findById("5ffbfe8197f24a07007bd6ce").get();
        user.setName("张三_1");
        user.setAge(25);
        user.setEmail("883220990@qq.com");

        // 如果有id 就是修改操作 否则是添加操作
        User save = userRepository.save(user);
        System.out.println(save);
    }

    //删除
    @Test
    public void delete() {
        userRepository.deleteById("5ffbfe8197f24a07007bd6ce");
    }
}

pring Data提供了对mongodb数据访问的支持,我们只需要继承MongoRepository类,按照Spring Data规范就可以了。


不是随便声明的,而需要符合一定的规范。
查询方法以find | read | get开头。
涉及条件查询时,条件的属性用条件关键字连接。条件属性首字母需要大写
支持属性的级联查询,但若当前类有符合条件的属性则优先使用,而不使用级联属性,若需要使用级联属性,则属性之间使用_强制进行连接。

原文地址:https://www.cnblogs.com/itlihao/p/14559435.html