首页 > 数据库 >MongoDB 笔记

MongoDB 笔记

时间:2023-02-08 18:56:24浏览次数:48  
标签:name MongoDB db 笔记 索引 文档 集合

title: MongoDB 笔记
date: 2023-02-03 11:13:35
tags:
- MongoDB

1、MongoDB 相关概念

<DataBase>

mongodb中的就类似于传统关系型数据库中的概念,用来通过不同库隔离不同应用数据。

mongodb中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为"test",数据库存储在启动指定的data目录中。

集合 <collection>

集合就是 MongoDB文档组,类似于RDBMS(关系数据库管理系统: RelationalDatabase Management System)中的的概念。

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

文档 <Document>

文档集合中一条条记录,是一组键值(key-value)对(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点。

2、库的相关操作

查看所有库

> show databases; | show dbs
  • admin:从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config:当Mongo用于分片设置时, config数据库在内部使用,用于保存分片的相关信息。

创建数据库

> use 库名

删除数据库

  • 默认删除当前选中的库
> db.dropDatabase()

查看当前所在库

> db;

3、集合的相关操作


查看库中所有集合

> show collections; | show tables;

创建集合

> db.createCollection('集合名称', [options])

options 可以是如下参数:

字段 类型 描述
capped 布尔 (可选)如果为true,则创建固定集合。固定集合是指有着固定大小布尔的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为true时,必须指定size参数。
size 数值 (可选)为固定集合指定一个最大值,即字节数。如果capped为true,也需要指定该字段。
max 数值 (可选)指定固定集合中包含文档的最大数量。

注意:当集合不存在时,向集合插入该文档也会自动创建该集合。

4、文档

插入

插入文档

  • 多条文档

    > db.集合.insert({
    	username: "sunwukong"
    });
    
  • 多条文档

    > db.集合名称.insertMany(
    	 [<document 1>, <document 2>],
        {
        	writeConcern: 1,  // 写入策略,默认为1,即要求确认写作,0是不要求
        	ordered: true  // 指定是否按顺序写入,默认true,按顺序写入
        }
    )
    
    > db.集合.insert([
    	{username: "金俊菀"},
    	{username: "安正源"},
    ])
    
    
  • 脚本方式

    for (int i = 0; i < 100; i ++ ) {
    	db.users.insert({"_id": i, "name": "yisheng_" + i, "age": 23})
    }
    
    

删除文档

删除文档

db.colection.remove(
	<query>,
   {
   		justOne: <boolean>,
    	writeConcern: <document>
   }
)

参数说明:

  • query :可选删除的文档的条件。
  • justOne:可选如果设为true或1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern:可选抛出异常的级别。

更新文档

更新文档

db.colection.update(
	<query>,
   {
   		justOne: <boolean>,
    	writeConcern: <document>
   }
)

参数说明:

  • query :update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  • upsert:可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi:可选,mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern:可选,抛出异常的级别。
- db.集合名称.update( {" name" : "zhangsan" } , {name : "11" , bir:new date()})`
	这个更新是将符合条件的全部更新成后面的文档,相当于先删除在更新`
- db.集合名称.update( { " name" : "xiaohei" } ,{$set: {name : "mingming"}})
	保留原来数据更新,但是只更新符合条件的第一条数据
- db.集合名称.update( {name :"小黑"},{$set: {name: "小明"}},{multi:true})
	保留原来数据更新,更新符合条件的所有数据
- db.集合名称.update( {name :"小黑"},{$set : {name : "小明”}},{multi:true, upsert:true })
    保留原来数据更新,更新符合条件的所有数据没有条件符合时插入数据

查询文档

查询所有

> db.集合名称.find(query, projection)
  • query∶可选,使用查询操作符指定查询条件
  • projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。

如果需要以易读的方式来读取数据,可以使用pretty()方法,语法格式如下:

> db.集合名称.find().pretty()

MongoDB 与 RDBMS Where 语句比较

image

AND 条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

语法格式如下:

> db.collection.find({key1:value1, key2:value2}).pretty()

e.g.: WHERE by='菜鸟教程' AND title='MongoDB 教程'

> db.collection.find({"by": "菜鸟教程", "title": "MongoDB 教程"}).pretty()

OR 条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

> db.col.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()

e.g. : by 值为 菜鸟教程 或键 title 值为 MongoDB 教程

> db.col.find({
	$or: [
        {"by": "菜鸟教程"},
        {"title": "MongoDB 教程"}
    ]     
}).pretty()

AND 和 OR 联合使用

e.g: 类似常规 SQL 语句为: 'where likes>50 AND (by = '菜鸟教程' OR title = 'MongoDB 教程')'

db.col.find({ 
   "likes": {$gt: 50},
	$or: [
        {"by": "菜鸟教程"},
        {"title": "MongoDB 教程"}
    ]     
}).pretty()

模糊查询

类似SQL中 where name like '%name%'

> db.col.find({likes: /良/})

注意:在mongoDB中使用 正则表达式 可以实现近似模糊查询功能

排序

> db.集合名称.find().sort({name : 1 ,age:1})
    1 升序  -1 降序

类似SQL中 order by name, age

分页

> db.集合名称.find().sort({条件}).skip(start).limit(rows)

类似SQL中 limit start, rows

总条数

> db.集合名称.count();
> db.集合名称.find({"name": "小张"}).count();

类似SQL中 select count(id) from ...

去重

> db.集合名称.dinstinct('字段')

指定返回名称

> db.集合名称.find({条件}, {name: 1, age: 1})
	1 返回  0 不返回   注意:1和0不能同时使用

$type

$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。

MongoDB 中可以使用的类型如下表所示:

image

e.g.

> db.col.insert({
    title: 'PHP 教程', 
    description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['php'],
    likes: 200
})

>db.col.insert({title: 'Java 教程', 
    description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['java'],
    likes: 150
})

> db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb'],
    likes: 100
})

如果想获取 "col" 集合中 title 为 String 的数据,可以使用以下命令:

> db.col.find({"title": {$type: 2}})   // 参考上述表格中的类型对应的数字
或
> db.col.find({"title": {$type: 'string'}})

索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

操作

创建索引

> db.集合名称.createIndex(keys, options)
> db.集合名称.createIndex({"title": 1, "description": -1})

说明:语法中Key值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

createIndex() 接收可选参数:

Parameter Type Description
background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加"background"可选参数。"background”默认值为false。
unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
expireAfterSeconds integer 指定一个以秒为单位的数值,完成TTL设定,设定集合的生存时间。

1、查看集合索引

> db.集合名称.getIndexes() 

2、查看集合索引大小

> db.集合名称.totalIndexSize()

3、删除集合所有索引

> db.集合名称.dropIndexes()

4、删除集合指定索引

> db.集合名称.dropIndex()

复合索引

说明:一个索引的值是由多个key进行维护的索引 称之为复合索引

> db.集合名称.createIndex({"title": 1, "description": -1})

注意:mongoDB中复合索引 和 传统关系型数据库一致,都是左前缀原则(B+树)

聚合 aggregate() 方法

MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似 SQL语句中的 count(*)

MongoDB中聚合的方法使用aggregate()。

aggregate() 方法的基本语法格式如下所示:

> db.集合名称.aggregate(AGGREGATE_OPERATION)

eg:集合中的数据如下:

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'Neo4j',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:

> db.col.aggregate([{$group: {_id: {"by_user"}, num_tutorial: {$sum: 1}} }])  

以上实例类似sql语句:

> select by_user, count(*) from mycol group by by_user

在上面的例子中,我们通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。

下表展示了一些聚合的表达式:

image

5、整合SpringBoot----MongoTemplate

pom.xml

<!--SpringBoot整合MongoDB-->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--MongoDB相关依赖-->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>3.9.1</version>
</dependency>

配置文件:

# mongodb 无密码
spring.data.mongodb.uri=mongodb://localhost:27017/demos

# mongodb 存在密码
#spring.data.mongodb.host =
#spring.data.mongodb.port =
#spring.data.mongodb.database =
#spring.data.mongodb.username =
#spring.data.mongodb.password =

首先使用@Autowired注入MongoTemplate

@Autowired
private MongoTemplate mongoTemplate;

相关注解

@Document

  • 修饰范围:用在类上
  • 作用:用来映射这个类的一个对象为mongo中一条文档数据。
  • 属性:( value . collection )用来指定操作的集合名称

@Id

  • 修饰范围:用在成员变量、方法上
  • 作用:用来将成员变量的值映射为文档的_id的值.

@Field

  • 修饰范围:用在成员变量、方法上
  • 作用:用来将成员变量以及值映射为文档中一个key、value对
  • 属性:( name, value )用来指定在文档中 key的名称,默认为成员变量名

@Transient

  • 修饰范围:用在成员变量、方法上
  • 作用:用来指定改成员变量,不参与文档的序列化

创建集合

@Test
public void testCreateCollection() {
    boolean exists = mongoTemplate.collectionExists("products");
    if(!exists){
        mongoTemplate.createCollection("products");
    }
}
  • 注意:创建集合不能存在,否则会报错

删除集合

@Test
public void testDropCollection() {
    mongoTemplate.dropCollection("products");
}

文档操作

添加

User.java

@Document(value = "users")
public class User {

    @Id
    private Integer id;
    @Field("username")
    private String name;
    @Field
    private Double salary;
    @Field
    private Date birthday;

    // 构造方法等我省略了。。。
}

insert

@Test
public void test() {
    User user = new User(2, "小张", 2300.0, new Date());
    //  保存对象到mongodb
    mongoTemplate.insert(user);
    mongoTemplate.save(user);
}
  • insert:插入重复数据时,insertDuplicateKeyException 提示主键重复;save 对已存在的数据进行更新。
  • save:批处理操作时,insert 可以一次性插入整个数据,效率较高;save 需要便利整个数据,一次插入或更新,效率极低。

查询

@Test
public void testFind() {
    // 1. 查询所有
    mongoTemplate.findAll(User.class);

    // 2. 基于 id 查询一个
    Object byId = mongoTemplate.findById(2, User.class);
    System.out.println("基于id查询一个用户:" + byId);

    // 3. 条件查询,添加查询 参数1:查询条件 参数2:返回类型
    mongoTemplate.find(new Query(), User.class);

    // 4. 等值查询
    mongoTemplate.find(Query.query(Criteria.where("username").is("小张")), User.class);

    // 5. > < >= <= 查询
    mongoTemplate.find(Query.query(Criteria.where("salary").lt(2300)), User.class);

    // 6. and 查询
    mongoTemplate.find(Query.query(Criteria.where("name").is("小张").and("salary").is(2300.0)), User.class);

    // 7. or 查询
    Criteria criteria = new Criteria();
    criteria.orOperator(
        Criteria.where("name").is("小张"),
        Criteria.where("name").is("小李"),
        Criteria.where("age").lt(20000)
    );
    mongoTemplate.find(new Query(criteria), User.class);

    // 8. and or 连用

    Criteria criteria1 = new Criteria().and("age").is(23)
        .orOperator(Criteria.where("name").is("小张"),
                    Criteria.where("name").is("小张"));
    mongoTemplate.find(Query.query(criteria1), User.class);

    // 9. 排序
    Query querySort = new Query();
    querySort.with(Sort.by(Sort.Order.asc("salary")));
    mongoTemplate.find(querySort, User.class);

    // 10. 分页查询
    Query querySortPage = new Query();
    querySortPage.with(Sort.by(Sort.Order.asc("salary")))
        .skip(0).limit(2);
    List<User> users = mongoTemplate.find(querySortPage, User.class);
    users.forEach(System.out::println);

    // 11. 查询总条数
    long count = mongoTemplate.count(new Query(), User.class);

    long count1 = mongoTemplate.count(Query.query(Criteria.where("name").is("小张")), User.class);
    System.out.println(count + ", " count1);

    // 12. 去重
    // 参数1:查询条件 参数2:去重字段 参数3:操作集合 参数4:返回类型
    List<String> stringList = mongoTemplate.findDistinct(new Query(), "name", User.class, String.class);
    stringList.forEach(System.out::println);
    
    // 13. 使用json字符串方式查询
    BasicQuery basicQuery = new BasicQuery("{name: '小张', age: 18}");
    BasicQuery basicQuery1 = new BasicQuery("{$or:[{name: '小张'}, {name: '小李'}]}", "{name: 1, age: 1}");

    mongoTemplate.find(basicQuery, User.class);

}

更新

@Test
public void testUpdate() {
    // 1. 更新条件
    Query query = Query.query(Criteria.where("name").is("小张"));
    // 2. 更新内容
    Update update = new Update();
    update.setOnInsert("id", 5);
    update.set("salary", 5000);
    // 单条更新
    mongoTemplate.updateFirst(query, update, User.class);
    // 多条更新
    mongoTemplate.updateMulti(query, update, User.class);
    // 更新插入
    UpdateResult updateResult = mongoTemplate.upsert(query, update, User.class);

    // 获取本次修改记录
    System.out.println(updateResult.getModifiedCount());
    // 获取本次匹配的记录
    System.out.println(updateResult.getMatchedCount());
    // 拿到插入时生成的id,upsertid
    System.out.println(updateResult.getUpsertedId());
}

删除

@Test
public void testRemove() {
    // 删除所有
    mongoTemplate.remove(new Query(), User.class);

    // 条件删除
    mongoTemplate.remove(Query.query(Criteria.where("name").is("小张")), User.class);
}

标签:name,MongoDB,db,笔记,索引,文档,集合
From: https://www.cnblogs.com/stdxiaozhang/p/17102968.html

相关文章

  • 离线地图的开发笔记(一)
    最近做一个项目,用到离线谷歌地图的开发,而现在谷歌地图在中国的发展不是很完美,导致项目的定项迟迟不能决定。后来制作了一个地图插件mymapw.ocx,完美地解决了Winform窗体里......
  • 算法学习笔记(15): Trie(字典树)
    Trie树Trie(字典树)是一种用于实现字符串检索的多叉树。Trie的每一个节点都可以通过c转移到下一层的一个节点。我们可以看作可以通过某个字符转移到下一个字符串状态,直......
  • MongoDB学习笔记二(插入、更新)
    1、插入 runCommand insert:后面写集合名称ordered:可选,布尔值。如果true,则当插入文档失败时,返回而不插入inserts数组中列出的任何剩余文档。如果false,则当插入一个文......
  • 学习笔记(ResNet)
    1、介绍ResNet,ResNetV2,ResNeXt模型,权值由ImageNet训练而来。ImageNet数据是CV领域非常出名的数据集,ISLVRC竞赛使用的数据集是轻量版的ImageNet数据集。ISL......
  • pytorch学习笔记2
    pytorch学习笔记2   RNN结构图pytorch保存模型方法Pytorch有两种保存模型的方式,都是通过调用pickle序列化方法实现的。第一种方法只保存模型参数。第二种方法......
  • 读Java实战(第二版)笔记04_用流收集数据
    1. 方便程序员和可读性是头等大事!1.1. 函数式API设计更易复合和重用2. 归约和汇总为一个值2.1. counting()2.1.1. 计数2.2. maxBy2.2.1. 查找流中的最大值2......
  • jenkins学习笔记之一:流水线基础语法
    一、Pipeline概念1node/agent(节点)节点是一个机器,可以是Jenkins的master节点也可以是slave节点。通过node指定当前job运行的机器(这个是脚本式语法)。参数:.any在任......
  • 小苗与大树的精选谈话笔记
    价值50元一节的看图学职场文化表达技巧课,我的课不贵,也就两包烟,50块钱!!!本来今天都没什么想法写文章,在这里我要感谢我可爱的同事,没有你,我今天的素材都没有,我都不知道要写啥,你......
  • Decoupling Zero-Shot Semantic Segmentation论文阅读笔记
    摘要现有的方法将零样本语义分割(Zero-shotsemanticsegmentation,ZS3)视为逐像素的zs分类,并且使用仅用文本预训练的模型来完成已知类到未知类的知识迁移,而文本图像预训练模......
  • 《分布式技术原理与算法解析》学习笔记Day04
    分布式选举算法为什么需要分布式选举?分布式意味着我们的应用部署在一个集群中,集群包含多个节点或者服务器,对于一个集群来说,多个节点是怎么协同工作的呢?我们需要有一个主......