MongoDB 数据库-自学

MongoDB 简介

MongoDB 数据库是一种 NoSQL 数据库,NoSQL 数据库不是这几年才有的,从数据库的初期发展就已经存在有了 NoSQL 数据库。数据库之中支持的 SQL 语句是由 IBM 开发出来的,并且最早就应用在了 Oracle 数据库,但是 SQL 语句的使用并不麻烦,就是几个简单的单词:SELECT、FROM、WHERE、GROUP BY、HAYING、ORDER BY。但是在这个时候有人开始反感于编写 SQL 操作。于是有一些人开始提出一个理论 ———— 不要去使用SQL,于是最早的 NoSQL 概念产生了。可是后来的发展产生了一点变化,在90年代到2010年之间,世界上最流行的数据库依然是关系型数据库,并且围绕着关系型数据库开发出了大量的程序应用,后来又随着移动技术(云计算、大数据)的发展,很多公司并不愿意使用大型的厂商数据库 ———— Oracle、DB2,因为这些人已经习惯于使用 MySQL 数据库了。这些人发现在大数据以及云计算的环境下,数据存储受到了很大的挑战,那么后来就开始重新进行了 NoSQL 数据库的开发,但是经过长期的开发发现,NoSQL 数据库依然不可能离开传统的关系型数据库(NoSQL、Not Only SQL)。

实际上在显示的开发中一直存在一种神奇的问题:

  • 数据表 -> JDBC 读取 -> POJO(VO、PO)-> 控制层转化为 JSON 数据 -> 客户端

可是这样的转换实在是太麻烦了,那么最好的做法是,直接有一个数据库就存放有要显示的 JSON 数据该有多好,那么就省略了所有需要进行转换的过程。所以在实际的开发之外还要提供有一个 NoSQL 数据库,其中 NoSQL 数据库负载数据的读取,因为直接保存的就是 JSON(前提:MongoDB 中的数据是排列好的组合数据)。

例如:现在要去显示出每个雇员的编号、姓名、职位、部门名称、工作等级。传统的关系型数据库,一定要存放大量的冗余数据,不合理。而有了 NoSQL 数据库之中,可以直接在业务层面讲数据交给 NoSQL 保存,按照指定的结构进行存储。

在 MongoDB 数据库之中与 Oracle 数据库有如下的概念对应:

No 关系型数据库 NoSQL 数据库
1 数据库 数据库(类似于 MySQL)
2 集合
3 文档
4 成员
5 主线 Object ID(自动维护的)

在整个行业之中,MongoDB 数据库是发展最好的一个 NoSQL 数据库,因为它于 Node.js 捆绑了。如果你要从事 Node.js 开发,那么一定要使用 MongoDB,而 Node.js 在国内最成功的应用 ———— 淘宝。

MongoDB 之所以能够更好的发展也取决于:面向集合的存储过程、模式自由(无模式)、方便的进行数据的存储扩充、支持索引、支持短暂数据保留、具备完整的数据库状态监控、基于 BSON 应用。


安装并配置 MongoDB

如果想要得到 MongoDB 数据库只需要登录 中文网 可以直接下载可用版本,最新的版本是 3.0.x,但是这版本变为了 windows 安装版(只是把原来的解压缩版变为了安装拷贝)。

将下载下来的 MongoDB 数据库直接进行安装。安装的时候需要选择好对应的操作系统,本次使用的是 64 位的安装版本。存放在 E:/ 盘

MongoDB 安装完成之后,严格来讲并不能够在 Windows 下使用,需要为它配置 path 环境属性 E:/MongoDB/bin

如果想要正常启动 MongoDB 数据库,那么必须建议一个文件夹,这个文件夹将保存所有的数据库的信息,现在将在 MongoDB 文件夹之中建立一个 db 的目录,并且在此目录下保存所有的数据文件。

MongoDB 数据库的启动需要使用 mongod.exe 命令完成,启动的时候可以设置端口号,也可以不设置端口号。

  • 不设置端口号启动 MongoDB 服务:mongod --dbpath E:/MongoDB/db
  • 设置端口号启动:mongod --dbpath E:/MongoDB/db --port=27000
    • 如果日后需要通过程序访问数据库的话,那么一定要设置端口号。

当 MongoDB 服务启动之后,可以使用 mongo 命令链接数据库

范例:查询所有的数据库 show databases 此时只存在有一个 local 的本地数据库,不过这个数据库不使用

虽然以上的代码实现了数据库的启动与链接操作,但是从严格意义上来讲,以上的代码没有任何用处,因为从实际的开发来讲,在 MongoDB 启动的时候需要设置一些相应参数:端口号、是否启用用户验证、数据文件的位置等等。

范例:在 E:/MongoDB 目录下建立一个文件 “mongodb.conf”

  • 同时建立了一个保存日志信息的文件:log/mongodb.log
  # 设置数据目录的路径
  dbpath = C:\Users\zhujunlin001\Desktop\MongoDB-self-study\mongodb-win32-x86_64-windows-4.4.2\db
  # 设置日志信息的文件路径
  logpath = C:\Users\zhujunlin001\Desktop\MongoDB-self-study\mongodb-win32-x86_64-windows-4.4.2\log\mongodb.log
  # 打开日志输出操作
  logappend = true
  # 表示目前为止不使用任何验证的登录,在以后进行用户管理的时候使用它
  noauth = true
  # 设置端口号
  port = 27001
  • 随后重新启动 MongoDB 数据库服务:
    • 切换到 admin 数据库:use admin
    • 关闭数据库服务:db.shutdownServer()
    • 重新启动服务:mongod -f e:\MongoDB\mongodb.conf
      mongod -f C:\Users\zhujunlin001\Desktop\MongoDB-self-study\mongodb-win32-x86_64-windows-4.4.2\mongodb.conf

范例:链接数据库
此时服务器已经存在有指定的端口号了。mongo --port=21001
使用端口号启动在日后的程序开发部分是非常有用处的。


MongoDB 的基础操作

在 MongoDB 数据库里面是存在数据库的概念,但是没有模式(所有的信息都是按照文档保存的)保存数据的结构就是 JSON 结构,只不过在进行一些数据处理的时候才会使用到 MongoDB 自己的一些操作符。

  1. 使用 mldn 数据库:use mldn
  • 实际上这个时候并不会创建数据库,只有在数据库里面保存集合数据之后才能够真正创建数据库
  1. 创建一个集合 ———— 创建一个 emp 集合
  • db.createCollection("emp")
  • 这个时候 mldn 数据库才会真正的存在。
  1. 但是很多的时候如果按照以上的代码形式进行会觉得你不正常,因为正常人使用 MongoDB 数据库集合操作的时候,都是直接向里面保存一个数据。
  • 执行:db.dept.insert({"deptno":10, "dname":"财务部", "loc":"北京"})
  1. 查看所有集合 show collections
    发现 dept 集合自动创建了。
  2. 查看 emp 表的数据
  • 语法:db.集合名称.find({若干条件})
  • 执行:db.dept.find()
    从传统的数据表来看(集合就想到与表的结构),表的结构一旦定义就必须按照其定义的要求进行内容的编写,但是 MongoDB 不一样,它可以自己随意扩充数据。
  1. 增加不规则数据
  var deptData = {
    "deptno": 20,
    "dname": "研发部",
    "loc": "深圳",
    "count": 20,
    "avg": 8000
  }
  db.dept.insert(deptData)

此时 dept 集合的内容可以有用户随便去定义,完全不用考虑其它的结构,那么实际上就必须明确一点了,在 MongoDB 数据库之中是绝对不可能存在查看集合结构的操作。
7. 关于 ID 的问题
在 MongoDB 集合中的每一行记录都会自动的生成一个 "_id": ObjectId("1234987sadf90980989sadf") 数据,这个组成是:时间戳 + 机器码 + PID + 计数器
这个 ID 的信息是 MongoDB 数据库自己为用户生成的

  1. 查看单独的一个文档信息
    db.dept.findOne()

  2. 删除数据
    db.dept.remove({"_id": ObjectId("1234987sadf90980989sadf")})

  3. 更新数据

    var deptData = {
    "deptno": 21,
    "dname": "家里蹲",
    "loc": "北京",
    "count": 20,
    "avg": 8100
  }
db.dept.updata({"_id": ObjectId("1234987sadf90980989sadf")}, deptData)
  1. 删除集合
  • 语法:db.集合名称.drop()
  • 这里执行:db.dept.drop()
  1. 删除数据库(删除当前所在的数据库)
    db.dropDatabase() 删除数据库的是,删除当前所在的数据库,必须先切换到数据库后,才能删除。

数据操作(重点)

只要是数据库,那么就绝对离不开最为核心的功能:CRUD(增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)),所以在 MongoDB 里面对于数据的操作也是有支持的,但是需要提醒的是,除了增加之外,其它的都很麻烦。

数据增加

  • 使用:db.集合.insert()可以实现数据的增加操作
    • 范例:增加一个简单数据 db.infos.insert({"url":"www.mldn.cn"})
    • 范例:增加一个数组db.infos.insert([{"url":"www.mldn.cn"}, {"url":"www.mldnjava.cn"}])
      如果要想保存多个数据,那么就使用数组。
    • 范例:保存 10000 个数据?
        for (var x = 0; x < 10000; x ++) {
          db.infos.insert({"url": "mldn -" + x});
        };
      
      如果数据保存很多的情况下,列表时不会全部列出,它只会列出部分的内容

数据的查询操作

任何的数据库之中,数据的查询操作都是最为麻烦的,而在 MongoDB 数据库里面,对于查询的支持非常的到位,包含有关系运算、逻辑运算、数组运算、正则运算等等。

首先对于数据的查询操作核心的语法:db.集合.find({查询条件}[,{设置显示的字段}])

范例:最简单的用法就是直接使用 find() 函数完成查询 db.infos.find()

范例:希望查询出 url 为 “www.mldn.cn” 的数据 db.infos.find({"url": "www.mldn.cn"})

发现在进行数据查询的时候也是按照 JSON 形式设置的相等关系。它的整个开发之中都不可能离开 JSON 数据。
对于设置的显示字段严格来讲就称为数据的投影操作,如果不需要显示的字段设置“0”,而需要显示的字段设置为“1”。

范例:不想显示 “_id” db.infos.find({"url": "www.mldn.cn"}, {"_id": 0, "url": 1})

大部分情况下,这种投影操作的意义不大。同时对于数据的查询也可以使用 “pretty()” 函数进行漂亮显示

范例:漂亮显示 db.infos.find({"url": "www.mldn.cn"}, {"_id": 0, "url": 1}).pretty()

数据列多的时候一定可以看出华丽的显示效果。其实就是将数据排好格式了。

范例:查询单个数据 db.infos.findOne({"url": "www.mldn.cn"}, {"_id": 0, "url": 1})

利用以上的查询可以实现格式化的输出效果,前提:列的内容必须多。

条件过滤

实际上习惯于传统关系型数据库开发的我们对于数据的筛选,肯能首先想到的一定是 where 字句,所以在 MongoDB 里面也提供有“$where”。

  1. $exists
    + 语法:{ field: { $exists: <boolean> } }
    + $exists如果为true,则选择包含该字段的文档。如果为false,则查询仅返回不包含该字段的文档。null ?不返还

  2. $where
    +
    + 范例:使用 where 进行数据查询 db.students.find({"$where": "this.age>20"}).pretty()
    + 简化 db.students.find("this.age>20").pretty()
    对于“$where”是可以简化的,但是这类的操作是属于进行每一行的信息判断,实际上对于数据量较大的情况并不方便使用。实际上以上的代码严格来讲是属于编写一个操作的函数。
    MongoDB 的语法完全可以使用 JavaScript 来写,所以以上代码等同于(也可以用一下写法)

```javascript
  db.students.find(function() {
    return this.age > 20;
  }).pretty();

  // 或者
  db.students.find({"$where": function() {
    return this.age > 20;
  }}).pretty();
```

一上只是实现了一个条件的查询,如果要实现对个条件的判断查询,那么就需要使用 and 连接。

  1. $and
    范例:在 students 集合里找到年龄是 20 的人:
```javascript
  db.students.find({"$and": [
    {"$where": "this.age > 19"},
    {"$where": "this.age < 21"}
  ]}).pretty();
```

虽然这种形式的操作可以实现数据查询,但是最大的缺点是将在 MongoDB 里面保存的 BSON 数据变为了 JavaScript 的语法结构,这样的方式不方便使用数据库的索引机制。

正则运算

如果要实现模糊查询,那么必须使用正则表达式,而且正则表达式使用的语言 Perl 兼容的正则表达式的形式。如果要想实现正则使用,则按照如下的格式定义:

  • 基础语法:{key: 正则标记}
  • 完整语法:{key:{"$regex": 正则标记, "$options": 选项}}
    • 对应 options 主要是设置正则的信息查询的标记:
      • “i”:忽略字母大小写
      • “m”:多行查找
      • “x”:空白字符除了被转义的或在字符类中意外的完全被忽略
      • “s”:匹配所有的字符(圆点、“.”),包括换行内容
    • 需要注意的是,如果是直接使用(JavaScript)那么只能够使用 i 和 m,而“x”和“s”必须使用“$regex”

范例:查询以 “谷” 开头的姓名

  db.students.find({"name": /谷/}).pretty();

范例:查询名字中有字母 A 的

  db.students.find({"name": /a/i}).pretty();

  // 完整的格式写法
  db.students.find({"name": {"$regex": /a/i}}).pretty();

如果要执行模糊查询的操作,严格来讲只需要编写一个关键字就够了。
正则操作之中除了可以查询出单个字段的内容之外,也可进行数组数据的查询。

范例:查询数组数据: course 课程,是个数组,现需要查询这个数组中的课程带“语”关键字的数据

  db.students.find({"course": /语/}).pretty();

  // 或者
  db.students.find({"course": /语?/}).pretty();

MongoDB 中的正则符号和之前 java 正则是有一些差别的,不建议使用以前的一些标记,正则就将其应用在模糊数据的查询上

数据排序

在 MongoDB 里面数据的排序操作使用 “sort()” 函数,在进行排序的时候可以有两个顺序:升序(1)、降序(-1)。
范例:按成绩"score"经行倒序排。

  db.students.find().sort("score": -1).pretty();

但是在进行排序的过程里面有一种方式称为自然排序,按照数据保存的先后顺序排序,使用“$natural”。
范例:自然排序

  db.students.find().sort("$natural": -1).pretty();

在 MongoDB 数据库里面排序的操作相比较传统关系型数据库的设置要简单。

分页控制

在 MongoDB 里面的数据分页显示也是符合于大数据要求的操作函数:

  • skip(n): 表示跨过多少数据行
  • limit(n): 取出的数据行的个数限制。
    范例:分页显示(第一页,skip(0)、limit(5))
  db.students.find().skip(0).limit(5).sort({"age": 1}).pretty();

范例:分页显示(第二页,skip(5)、limit(5))

  db.students.find().skip(5).limit(5).sort({"age": 1}).pretty();

这两个分页的控制操作,就是在以后只要是存在有大数据的信息情况下都会使用它。

更新函数(数据更新操作)

对于 MongoDB 而言,数据的更新基本上是一键很麻烦的事情,如果在实际的工作之中,真的具有此类的操作支持,那么最好的做法:
在 MongoDB 里面对于数据的更新操作提供了两类函数: save()、updata()。

函数的基本使用

如果要修改数据最直接的使用函数就是 updata(),但是这个函数的语法要求很麻烦:

  • 语法:db.集合.updata(更新条件,新的对象数据(更新操作符),upsert,multi)
    • upsert:如果要更新的数据不存在,则增加一条新的内容(true为增加,false为不增加)
    • multi:表示是否只更新满足条件的第一行记录,如果设置为false只更新第一个,如果是true全更新
      范例:更新存在的数据 ———— 将年龄是19岁的人的成绩"score"都更新为100分(此时会返回对跳数据)
  • 选择只更新第一天数据
  db.students.updata({"age": 19}, {"$set": {"score": 100}}, false, false);
  • 所有满足条件的数据都更新
  db.students.updata({"age": 19}, {"$set": {"score": 100}}, false, true);

范例:更新不存在的数据 ————

  db.students.updata({"age": 30}, {"$set": {"name": "不存在"}}, true, false);

由于没有年龄是30岁的学生信息,所以此时相当于进行了数据的创建。

那么处理 updata() 函数之外还提供有 save() 函数,这个函数的功能与更新不存在的内容相似。
范例:使用 save() 操作

  db.students.save({"_id": ObjectId("55932d0f2eeds37d002")}, "age": 50);

由于此时对应的id数据存在了,所以就变为了更新操作,但是如果要保存的数据不存在(不能保存有"_id"),那么就变为了增加操作

一般来说更新操作建议使用 updata()

修改器

对应 MongoDB 数据库而言,数据的修改会牵扯到内容的变更、结构的变更(包含有数组),所以在进行 MongoDB 设计的时候就提供有一系列的修改器的应用,那么像之前使用的 “$set” 就是一个修改器

  1. $inc: 主要正对于一个数字字段,增加某个数字字段的数据内容。
  • 语法:{"$inc": {"成员": 内容}}
    范例:将所有年龄为19岁的学生,成绩一律减少30分,年龄加一岁。
  db.students.updata({"age": 19}, {"$inc": {"score": -30, "age": 1}}, false, true);
  1. $set: 进行内容的重新设置
  • 语法:{"$set": {"成员": 新内容}}
    范例:将年龄为20岁的人的成绩修改为 89 分
  db.students.updata({"age": 20}, {"$set": {"score": 89}}, false, true);
  1. $unset: 删除某个成员的内容
  • 语法:{"$unset": {"成员": 1}}
    范例:删除"张三"的年龄与成绩的信息
  db.students.updata({"name": "张三"}, {"$unset": {"age": 1, "score": 1}});
  1. $push: 相当于将内容追加到指定成员之中(基本上是数组)
  • 语法:{"$push": {"成员": value}}
    范例:向"张三"添加课程信息(此时“张三”信息下没有 course 信息)
  db.students.updata({"name": "张三"}, {"$push": {"course": "语文"}});

范例:向"谷大神"的课程信息追加"美术"(此时“谷大神”信息下有 course 信息)

  db.students.updata({"name": "谷大神"}, {"$push": {"course": "美术"}});

就是进行数组数据的添加操作使用的,如果没有数组则进行一个新的数组的创建,如果有这进行内容的最加

  1. $pushAll: 与 "$push" 是类似的,可以一次最加多个内容到数组里
  • 语法:{"$pushAll": {"成员": 数组内容}}
    范例:向"王五"的信息里面添加多个课程内容
  db.students.updata({"name": "王五"}, {"$pushAll": {"course": ["语文", "美术"]}});
  1. $addToSet:向数组里面增加一个新的内容,只有这个内容不存在的时候才会增加
  • 语法:{"$addToSet": {"成员": 内容}}
    范例:向"王五"的课程信息里面增加新的内容
  db.students.updata({"name": "王五"}, {"$addToSet": {"course": "语文"}});

"语文"之前已存在,不会向数组最加内容,如果不存在,则会追加
7. $pop: 删除数组内的数据

  • 语法:{"$pop": {"成员": 内容}},内容如果设置为 1 表示删除第一个,如果是 -1 表示删除最后一个
    范例:删除"王五"的课程信息里面的第一个课程
  db.students.updata({"name": "王五"}, {"$pop": {"course": -1}});

范例:删除"王五"的课程信息里面的最后一个课程

  db.students.updata({"name": "王五"}, {"$pop": {"course": 1}});
  1. $pull:从数组内删除一个指定内容的数据
  • 语法:{"$pull": {"成员": 数据}},进行数据比对的,如果是此数据则删除
    范例:删除"王五"的"音乐"课程信息
  db.students.updata({"name": "王五"}, {"$pull": {"course": "音乐"}});
  1. $pullAll: 一次性删除多个内容
  • 语法:{"$pull": {"成员": [数据, 数据, 数据]}}
    范例:删除"王五"的三门课程信息
  db.students.updata({"name": "王五"}, {"$pullAll": {"course": ["音乐", "英语", "数学"]}});
  1. $rename: 为成员名称重命名
  • 语法:{"$rename": {"旧的成员名称": "新的成员名称"}}
    范例:将"张三"成员名称修改为"姓名"
  db.students.updata({"name": "张三"}, {"$rename": {"name": "姓名"}});

在整个 MongoDB 数据库里面,提供的修改器的支持很到位。

数据删除

在 MongoDB 里面的数据的删除实际上并不复杂,只需要使用"remove()"函数就可以了
这个函数是有两可选项的:

  • 删除条件:满足条件的数据被删除
  • 是否只删除一个数据,如果设置为true或者是1表示只删除一个。
    范例:清空 infos 集合中的内容
  db.infos.remove({});

范例:删除所有姓名里面带有"谷"的信息

  db.students.remove({"name": /谷/});

范例:删除姓名里面带有"高"的信息,要求只删除一个

  db.students.remove({"name": /高/}, true);

删除操作里面依然需要使用限定查询的相关操作内容。

关系运算(关系查询)

在 MongoDB 里面支持的关系查询操作:大于($gt)、小于($lt)、大于等于($gte)、小于等于($lte)、不等于($ne)、等于(key: value、$eq)。但是要想让这些操作可以正常使用,那么需要准备出一个数据集合
范例:定义一个学生信息集合

  db.students.drop();

  db.students.insert({"name": "张三", "sex": "男", "age": 18 "score": 89, "address": "海淀区"});
  db.students.insert({"name": "李四", "sex": "男", "age": 18 "score": 56, "address": "崇文区"});
  db.students.insert({"name": "王五", "sex": "女", "age": 19 "score": 89, "address": "海淀区"});
  db.students.insert({"name": "赵六", "sex": "男", "age": 20 "score": 89, "address": "朝阳区"});
  db.students.insert({"name": "孙七", "sex": "女", "age": 19 "score": 100, "address": "西城区"});
  db.students.insert({"name": "金八", "sex": "男", "age": 18 "score": 89, "address": "海淀区"});
  // ...

范例:查询姓名是张三的学生信息

  db.students.find({"name": "张三"}).pretty();

范例:查询年龄大于19岁的学生信息

  db.students.find({"age": {"$gt": 19}}).pretty();

范例:查询姓名不是王五的信息

  db.students.find({"name": {"$ne": "王五"}}).pretty();

此时于之前最大的区别就在于,在一个JSON结构里面需要定义其它的JSON结构,并且这种风格在日后通过程序进行操作的时候依然如此

逻辑运算

逻辑运算主要就是三种类型:于($and)、或($or)、非($not、$nor)
范例:查询年龄在 19~20 岁之间的学生信息

  db.students.find({"age": {"$gte": 19}, {"$lte": 20}}).pretty();

在进行逻辑运算的时候,$and 的连接是最容易的,因为只需要利用 “ , ” 分割若干个条件就可以了
范例:查询年龄不是 19 岁的学生信息

  db.students.find({"age": {"$ne": 19}}).pretty();

范例:查询年龄大于 19 岁,或者成绩大于 90 分的学生信息

  db.students.find(
    {
      "$or": [
        {
          "age": {"$gt": 19}
        }, 
        {
          "score": {"$gt": 90}
        } 
      ]
    }
  ).pretty();

范例:也可以进行或的求反操作

  db.students.find(
    {
      "$nor": [
        {
          "age": {"$gt": 19}
        }, 
        {
          "score": {"$gt": 90}
        } 
      ]
    }
  ).pretty();

针对于或的操作可以实现一个求反的功能。
在这几个逻辑运算之中,与的连接最简单,而或的连接需要为数据设置数组的过滤条件

模运算(求模)

模的运算使用 "$mod" 来完成,

  • 语法:{$mod:[数字,余数]}
    范例:求模(找到年龄是 20 余 0 的同学)
      db.students.find({"age": {"$mod": [20, 0]}}).pretty();
    

范围运算

只要是数据库,必须存在有 "$in"(在范围之中)、"$nin"(不在范围中)
范例:查询姓名是“张三”、“李四”、“王五”的信息

  db.students.find({"name": {"$in": ["张三"、"李四"、"王五"]}}).pretty();

范例:不在范围的查询 ———— 查询姓名不是“张三”、“李四”、“王五”的信息

  db.students.find({"name": {"$nin": ["张三"、"李四"、"王五"]}}).pretty();

在实际的工作之中,范围的操作很重要。

数组运算(数组查询)

首先在 MongoDB 里面是支持数组保存的,一旦支持了数组保存,就需要针对于数组的数据进行匹配。
范例:保存一部分的数组内容

  db.students.insert({"name": "谷大神 - A", "sex": "男", "age": 18 "score": 89, "address": "海淀区", "course": ["语文", "数学"]});
  db.students.insert({"name": "谷大神 - B", "sex": "男", "age": 18 "score": 89, "address": "海淀区", "course": ["语文", "数学", "英语"]});
  db.students.insert({"name": "谷大神 - C", "sex": "男", "age": 18 "score": 89, "address": "海淀区", "course": ["政治"]});

此时的数据包含有数组内容,而后需要针对于数组数据进行判断,可以使用几个运算符:"$all" "$size" "$slice" "$elemMatch"
范例:查询同时参加语文和数学课程的学生

  • 现在两个数组内容都需要保存,所以使用{"$all", [内容1,内容2]}
  db.students.find({"course": {"$all": ["语文", "数学"]}}).pretty();

现在所显示的学生信息里面包含语文和数学的内容信息,而如果差一个内容的都不会显示。
虽然 "$all" 计算可以用于数组上,但是也可以用于一个数据的匹配上
范例:查询地址是海淀区的学生

  db.students.find({"address": {"$all": ["海淀区"]}}).pretty();

既然在集合里面保存的是数组信息,那么数组就可以利用索引操作,使用 "key.index" 的方式来定义索引
范例:查询数组中第二个内容(index = 1,索引下标从 0 开始)为数学的信息

  db.students.find({"course.1": "数学"}}).pretty();

范例:要求查询出只参加两门课程的学生

  db.students.find({"course": {"$size": 2}}).pretty();

发现在进行数据查询的时候只要是内容符合条件,数组的内容就全部显示出来了,但是现在希望可控制数组的返回的数量,那么可以使用 "$slice" 进行操作
范例:返回年龄为 19 岁所有学生的信息,但是要求只显示两门参加的课程

  db.students.find({"age": 19}, {"course": {"$slice": 2}}).pretty();

现在只取得了前两门的信息,那么也可以设置负数,表示取得后两门的信息

  db.students.find({"age": 19}, {"course": {"$slice": -2}}).pretty();

或者只是取出中间部分的信息

  db.students.find({"age": 19}, {"course": {"$slice": [1, 1]}}).pretty();

在此时设置的两个数据里面第一个数据表示开始的索引,第二个数据表示截取的个数

嵌套元素查询(嵌套集合运算)

在 MongoDB 数据库里面每一个几何数据可以继续保持其它的集合数据,例如:有些学生需要保存家长信息
范例:增加数据

  db.students.insert({"name": "周杰伦 - A", "sex": "男", "age": 18 "score": 89, "address": "海淀区", "course": ["语文", "数学"],
    "parents": [
      {"name": "周杰伦 - A(父亲)", "age": 48, "job": "工人"},
      {"name": "周杰伦 - A(母亲)", "age": 44, "job": "职员"},
    ]
  });
  db.students.insert({"name": "周杰伦 - B", "sex": "男", "age": 19 "score": 89, "address": "海淀区", "course": ["语文", "数学", "英语"],
    "parents": [
      {"name": "周杰伦 - B(父亲)", "age": 52, "job": "处长"},
      {"name": "周杰伦 - B(母亲)", "age": 45, "job": "局长"},
    ]
  });
  db.students.insert({"name": "周杰伦 - C", "sex": "男", "age": 20 "score": 89, "address": "海淀区", "course": ["政治"],
    "parents": [
      {"name": "周杰伦 - C(父亲)", "age": 50, "job": "司机"},
      {"name": "周杰伦 - C(母亲)", "age": 48, "job": "老板"},
    ]
  });

此时给出的内容是嵌套的集合,而这种集合的数据判断只能够通过 "$elemMatch" 完成
范例:查询出父母有人是局长,年龄大于19岁的学生的信息

  db.students.find({"$and": [
    {"age": {"$gte": 19}},
    {"parents": {"$elemMatch": {"job": "局长"}}}
  ]}).pretty();

由于这种查询的时候条件比较麻烦,所以如果可能,尽量别搞这么复杂的数据结构组成。

成员是否存在查询(判断某个字段是否存在)

使用 "$exists" 可以判断某个字段是否存在,如果设置为true表示找的是存在,如果设置为false就表示不存在
范例:查询具有 "parents" 成员的数据

  db.students.find({"parents": {"$exists": true}}).pretty();

范例:查询不具有 "course" 成员的数据

  db.students.find({"course": {"$exists": false}}).pretty();

可以利用此类查询来进行一些不需要的数据的过滤

唯一索引

唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复。
范例:创建一个唯一索引

  db.students.ensureIndex({"name": 1}, {"unique": true}}).pretty();

在 name 字段上的内容绝对不允许重复
范例:在 students 集合里面增加重复的数据

    db.students.insert({"name": "张三", "sex": "男", "age": 18 "score": 89, "address": "房山区", "course": ["化学"]});

此时除了 name 字段上的内容之外,返现所有的数据都不一样,但是由于在 name 字段上设置了唯一的索引,所有程序里面如果增加了重复内容,那么会出现以下的错误提示信息:E11000 duplicate key error index:mldn.students.$name_1 dup key:......

阿里云产品简介:云数据库... 可以使用 MongoDB

阿里云数据库体验:数据库...

========================================================================

关于启动 MongDB 的 mongod.exe 遇到闪退问题解决办法

在 cmd 命令窗口按照官方安装MongoDB时遇到 启动 mongod.exe 闪退的问题,解决办法:在你安装 MongDB 的盘的根目录下,创建一个 db文件夹。我的是在 c 盘下 ,切记要在根目录下,然后需要先配置一下你要存储数据的地址,打开 cmd 命令窗口,进入到MongoDB\bin 目录下 输入:mongod --dbpath c:/db --port=27001 会出现。

实践:

  1. 在 MongoDB 根目录也就是 mongodb-win32-x86_64-windows-4.4.2 所在目录
    和 mongodb-win32-x86_64-windows-4.4.2\bin 目录下,启动服务器都成功了。
    - 可以用相对路径 比如:在 \bin 目录下执行 mongod --dbpath ../db --port=27001
  2. 网上说可以这样:带日志信息 mongod --dbpath ./db --dblog ./log/mongodb.log --port=27001
    提示:Error parsing command line: unrecognised option '--dblog' (解析命令行时出错:无法识别的选项'--dblog')

注意红色箭头部分。连接成功后就可以去浏览器打开http://localhost:27001 如果看到

It looks like you are trying to access MongoDB over HTTP on the native driver port.
则已经连接成功了。

posted @ 2020-11-25 18:34  真的想不出来  阅读(103)  评论(0编辑  收藏  举报