Day061MongoDB

mac2025-08-11  12

01. MongoDB 介绍

1. MongoDB介绍

MongoDB 是一个高性能,开源,无模式的文档型数据库,是当前noSql数据库产品中最热门的一种。它在许多场景下用于替代传统的关系型数据库或键值对存储方式,MongoDB是用C++开发

2. 为什么要用 NoSQL

2.1 NoSQL 简介

NoSQL,全称是”Not Only Sql”,指的是非关系型的数据库。这类数据库主要有这些特点:非关系型的、分布式的、开源的、水平可扩展的。原始的目的是为了大规模 web 应用,这场全新的数据库革命运动早期就有人提出,发展至 2009 年趋势越发高涨。NoSQL 的拥护者们提倡运用非关系型的数据存储,通常的应用如:模式自由、支持简易复制、简单的 API、最终的一致性(非 ACID)、大容量数据等。NoSQL 被我们用得最多的当数 key-value 存储,当然还有其他的文档型的、列存储、图型数据库、xml 数据库等。相对于目前铺天盖地的关系型数据库运用,这一概念无疑是一种全新思维的注入

2.2 发展现状

现今的计算机体系结构在数据存储方面要求应用架构具备庞大的水平扩展性,而NoSQL正在致力于改变这一现状。目前新浪微博的 Redis和 Google 的 Bigtable 以及 Amazon的 SimpleDB使用的就是 NoSQL 型数据库 NoSQL 项目的名字上看不出什么相同之处,但是,它们通常在某些方面相同:它们可以处理超大量的数据 这场革命目前仍然需要等待。NoSQL 对大型企业来说还不是主流,但是,一两年之后很可能就会变个样子。在 NoSQL 运动的最新一次聚会中,来自世界各地的 150 人挤满了 CBS Interactive 的一间会议室。分享他们如何推翻缓慢而昂贵的关系数据库的暴政,怎样使用更有效和更便宜的方法来管理数据 关系型数据库给你强加了太多东西。它们要你强行修改对象数据,以满足数据库系统的需要。在 NoSQL 拥护者们来看,基于 NoSQL 的数据库替代方案“只是给你所需要的”

2.3 为什么是 NoSQL

随着互联网 web2.0 网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展非常迅速,而传统的关系型数据库在应付 web2.0 网站,特别是超大规 模和高并发的 SNS 类型的 web2.0 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,例如:

High performance - 对数据库高并发读写的需求

web2.0 网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求

关系型数据库应付上万次 SQL 查询还勉强顶得住,但是应付上万次 SQL 写数据请求,硬盘IO 就已经无法承受了,其实对于普通的 BBS 网站,往往也存在对高并发写请求的需求

Huge Storage - 对海量数据的高效率存储和访问的需求

对于大型的 SNS 网站,每天用户产生海量的用户动态信息,以国外的 Friend feed 为例,一个月就达到了 2.5 亿条用户动态,对于关系数据库来说,在一张 2.5 亿条记录的表里面进行SQL 查询,效率是极其低下乃至不可忍受的。再例如大型 web 网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付

High Scalability&&HighAvailability-对数据库的高可扩展性和高可用性的需求

在基于 web 的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像 web server 和 app server 那样简单的通过添加

更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供 24 小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,可是停机维护随之带来的就是公司收入的减少

在上面提到的“三高”需求面前,关系数据库遇到了难以克服的障碍,而对于 web2.0 网站来说,关系数据库的很多主要特性却往往无用武之地,例如:   

数据库事务一致性需求

很多 web 实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求也不高。因此数据库事务管理成了数据库高负载下一个沉重的负担

数据库的写实时性和读实时性需求

对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于很多 web 应用来说,并不要求这么高的实时性

对复杂的SQL查询,特别是多表关联查询的需求

任何大数据量的 web 系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂 SQL 报表查询,特别是 SNS 类型的网站,从需求以及产品设计角度,就避免了这种情 况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL 的功能被极大的弱化了

因此,关系数据库在这些越来越多的应用场景下显得不那么合适了,为了解决这类问题的NoSQL 数据库应运而生。 ​ NoSQL 是非关系型数据存储的广义定义。它打破了长久以来关系型数据库与 ACID 理论大一统的局面。NoSQL 数据存储不需要固定的表结构,通常也不存在连接操作。在大数据存取上具备关系型数据库无法比拟的性能优势,该概念在 2009 年初得到了广泛认同。 当今的应用体系结构需要数据存储在横向伸缩性上能够满足需求。而 NoSQL 存储就是为了实现这个需求。 ​ Google 的 BigTable 与 Amazon 的 Dynamo 是非常成功的商业 NoSQL 实现。一些开源的 NoSQL 体系,如 Facebook的Cassandra,Apache的HBase,也得到了广泛认同。从这些NoSQL项目的名字上看不出什么相同之处:Hadoop、Voldemort、Dynomite,还有其它很多,但它们都有一个共同的特点,就是要改变大家对数据库在传统意义上的理解。

2.4 NoSQL 特点

它可以处理超大量的数据 它运行在便宜的 PC 服务器集群上 PC

集群扩充起来非常方便并且成本很低,避免了传统商业数据库“sharding”操作的复杂性和成本。

它击碎了性能瓶颈

NoSQL 的支持者称,通过 NoSQL 架构可以省去将 Web 或 Java 应用和数据转换成 SQL 格式的时间,执行速度变得更快。“SQL并非适用于所有的程序代码”,对于那些繁重的重复操作的数据,SQL 值得花钱。但是当数据库结构非常简单时,SQL 可能没有太大用处

它没有过多的操作

虽然 NoSQL 的支持者也承认关系型数据库提供了无可比拟的功能集合,而且在数据完整性上也发挥绝对稳定,他们同时也表示,企业的具体需求可能没有那么复杂

它的支持者源于社区

因为 NoSQL 项目都是开源的,因此它们缺乏供应商提供的正式支持。这一点它们与大多数开源项目一样,不得不从社区中寻求支持

2.5 MongoDB 特点

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似 json 的 bjson 格式,因此可以存储比较复杂的数据类型。MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库

面向集合(Collenction-Orented)

意思是数据被分组存储在数据集中, 被称为一个集合(Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表(table),不同的是它不需要定义任何模式(schema)

模式自由(schema-free)

意味着对于存储在 MongoDB 数据库中的文件,我们不需要知道它的任何结构定义。提了这么多次"无模式"或"模式自由",它到是个什么概念呢?例如,下面两个记录可以存在于同一个集合里面: {"welcome" : "Beijing"} {"age" : 25}

文档型

意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 “BSON” 即 “Binary Serialized document Notation.”

下面将分别介绍 MongoDB 的特点、功能和适用场合

特点 面向集合存储,易于存储对象类型的数据模式自由支持动态查询支持完全索引,包含内部对象支持查询支持复制和故障恢复使用高效的二进制数据存储,包括大型对象(如视频等)自动处理碎片,以支持云计算层次的扩展性支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++语言的驱动程序,社区中也提供了对 Erlang 及.NET 等平台的驱动程序文件存储格式为 BSON(一种 JSON 的扩展)可通过网络访问 功能 面向集合的存储:适合存储对象及 JSON 形式的数据动态查询:MongoDB 支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组完整的索引支持:包括文档内嵌对象及数组。MongoDB 的查询优化器会分析查询表达式,并生成一个高效的查询计划 查询监视:MongoDB 包含一系列监视工具用于分析数据库操作的性能复制及自动故障转移:MongoDB 数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器 适用场合 网站数据:MongoDB 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性缓存:由于性能很高,MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后,由 MongoDB 搭建的持久化缓存层可以避免下层的数据源过载大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储高伸缩性的场景:MongoDB 非常适合由数十或数百台服务器组成的数据库。MongoDB的路线图中已经包含对 MapReduce 引擎的内置支持用于对象及 JSON 数据的存储:MongoDB 的 BSON 数据格式非常适合文档化格式的存储及查询

3. MongoDB 下载

mongodb官网

mongodb.com/download-ce

fastdl.mongodb.org/win3

4. MongoDB GUI工具

Fang of Mongo – 网页式,由Django和jQuery所构成Futon4Mongo – 一个CouchDB Futon web的mongodb山寨版Mongo3 – Ruby写成MongoHub – 适用于OSX的应用程序Opricot – 一个基于浏览器的MongoDB控制台, 由PHP撰写而成Database Master — Windows的mongodb管理工具RockMongo — 最好的PHP语言的MongoDB管理工具,轻量级, 支持多国语言

02.Mongodb 安装(解压版)

1、解压到一个指定的路径 D:\Program Files\MongoDB 的目录下

2、先在当前文件下创建一个配置文件 mongo.conf , 如下添加配置内容

dbpath=D:\Program Files\MongoDB\data #数据库路径 logpath=D:\Program Files\MongoDB\logs\mongo.log #日志输出文件路径 logappend=true #错误日志采用追加模式 journal=true #启用日志文件,默认启用 quiet=true #这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false port=27017 #端口号 默认为27017

3、在D:\Program Files\MongoDB目录下创建 data 文件夹(数据库路径 ) 和 logs 文件夹(日志文件夹),logs目录下新建mongo.log文件。

4、在bin 目录下,启动命令行,输入:

mongod --config "D:\Program Files\MongoDB\mongo.conf"

(前面1~4的步骤时配置脚本,建议按照步骤执行。如果敲完第4步的命令,命令行出现等待的状态,不能再次输入则可关闭,继续执行下面的步骤)

5、不要关闭命令行页面,指定写入数据文件目录

mongod.exe --dbpath "D:\Program Files\MongoDB\data"

6、再在当前目录下启动 cmd ,启动一个命令行,输入

mongo.exe

如果能访问127.0.0.1:27017,说明服务已经启动成功了。

以上步骤是启动服务,只能在cmd 窗口启动的情况下,关闭cmd 命令行窗口就会终止服务。这时就需要添加系统服务里,不用每次使用都得启动一次。

7、将MongoDB加入windows服务,在bin 目录下启动 cmd (以管理员身份运行)键入以下命令:

mongod.exe --logpath "D:\Program Files\MongoDB\logs\mongo.log" --logappend --dbpath "D:\Program Files\MongoDB\data" --directoryperdb --serviceName MongoDB --install

如果提示失败的话 window不能启动非计算机的服务MongoDB

如果没有提示,则可在服务中查找看使得否已经出现MongoDB服务。一般刚创建好是停止的状态,这是只要点击启动即可。

处理方法:

1、删除MongoDB目录下data目录下的mongod.lock和storage.bson文件。

2、删除原本添加的MongoDB服务

sc delete 服务名称: sc delete MongoDB

3、重新添加MongoDB到系统服务

mongod.exe --logpath "D:\Program Files\MongoDB\logs\mongo.log" --logappend --dbpath "D:\Program Files\MongoDB\data" --directoryperdb --serviceName MongoDB --install

4、在windows 服务里查看MongoDB服务,显示是否已启动。

03. MongoDB 的使用

1. 启动mongodb

创建数据库目录, 如 /data/db , mongod --dbpath d:/data/db mongodb要求磁盘剩余空间>=4G,如果不够,可以用 --smallfiles 选项

2. MongoDB 与 Sql的概念对比

3. 数据类型

MongoDB中常用的几种数据类型

3.1 Object ID

每个文档都有一个属性,为_id,保证每个文档的唯一性可以自己去设置_id插入文档如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectIDobjectID是一个12字节的十六进制数前4个字节为当前时间戳接下来3个字节的机器ID接下来的2个字节中MongoDB的服务进程id最后3个字节是简单的增量值

4. mongodb最基础命令

show databases; #查看已有数据库use dataName; #选择数据库show tables; # 查看已有的表show collections # 同上,db.createCollection('表名');#建表db.表名.drop(); #删除表

注:table在mongodb里叫collections

5. collection与table的差异

5.1 table

特点:

有结构行遵循结构

5.2 collenction

{id:1,title:'晴空万里'} {id:2,title:'额...',data:'2018'}

特点:

collection无结构文档相互独立,没有固定结构

04. MongoDB 数据库的操作

1 Mongo数据库的操作

1.1 查看数据库

列出所有在物理上存在的数据库 show dbs

1.2 切换数据库/创建数据库

如果数据库不存在,则指向数据库,但不创建,直到插入数据或创建集合时数据库才被创建 use 数据库名

1.3 删除数据库

删除当前指向的数据库 如果数据库不存在,则什么也不做 use 数据库名 db.dropDatabase()

2 集合的操作

2.1 创建集合

db.createCollection(集合名,{capped:true,size:num}) capped:默认值为false表示不设置上限,值为true表示设置上限size:当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节

2.2 删除集合

db.集合名称.drop()

2.3 查看集合

show tables show collections

05. MongoDB 数据的简单操作

1 数据的操作

1.1 数据的增加

注意:插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectId

1.1.1 insert

db.集合名称.insert(document)

1.1.2 save

使用save函数里,如果原来的对象不存在,那他们都可以向collection里插入数据,如果已经存在,save会调用update更新里面的记录 db.集合名称.save(document)

1.1.3 举例

已存在数据: {_id : 'abc123', " name " : " 小王 " } ​ 再次进行插入操作时 insert({_id : 'abc123', " name " : " 小李 " }) 会报主键重复的错误提示 ​   

save({ _id : 'abc123', " name " : " 小李 " }) 会把 小王 修改为 小李 ​ 如果集合中不存在 _id : 'abc123', ​ insert({_id : 'abc123', " name " : " 小李 " }) 增加一条数据 ​ save({ _id : 'abc123', " name " : " 小李 " }) 增加一条数据

1.1.4 增加多条

db.集合名.insert([{k1:v1},{k2:v2}])

1.2 数据的修改

1.2.1 格式

db.集合名称.update( <query>, <update>, {multi: <boolean>} ) 参数query:查询条件,类似sql语句update中where部分参数update:更新操作符,类似sql语句update中set部分参数multi:可选,默认是false,表示只更新找到的第一条记录,值为true表示把满足条件的文档全部更新

1.2.2 举例

# 只更新找到的第一条,并且会修改结构 db.person.update({name:"zs"},{age:16}) # 只更新数据,为不更新文档结构 db.person.update({name:"zs"},{$set:{age:123}) # 更新所有找到匹配的数据 db.person.update({name:"zs"},{$set:{age:123}, {multi: true})

1.3 数据的删除

# 删除所有匹配数据 db.person.remove({name:"zs"}) # 只更新一条 db.person.remove({name:"zss"},{justOne:true})

1.4 数据的查找

db.集合名.find()

06. MongoDB 的查询

1. Mongo的简单查询

1.1 find

查找到所有匹配数据 db.集合名.find({条件文档})

1.2 findOne

只返回匹配的第一个数据 db.集合名.findOne({条件文档})

2. 运算符

举例

db.person.find({age:{$gt:16}}) db.person.find({$or:[{age:{$gte:18}},{name:"zs"}])

3. 模糊匹配

使用//或$regex编写正则表达式 db.person.find({name:/^zs/}) db.person.find({name:{$regex:'^zs'}}})

4. 自定义查询

使用$where后面写一个函数,返回满足条件的数据 db.person.find({$where:function(){return this.age>20}})

5. limit

用于读取指定数量的文档 db.集合名称.find().limit(NUMBER)

6. skip

用于跳过指定数量的文档 db.集合名称.find().skip(2)

7. sort

用于对结果集进行排序 db.集合名称.find().sort({字段:1,...}) 参数1为升序排列参数-1为降序排列

8. count

用于统计结果集中文档条数 db.集合名称.find({条件}).count()

9.$exists

判断是否有某个字段

db.集合名称.find({'field':{$exists:true}})

10.dictinct

去重

db.集合名称.distinct(field)

07. MongoDB 与 Python 交互

安装环境

pip install pymongo

使用样例:

1. 引入包pymongo

import pymongo

2. 连接,创建客户端

client = pymongo.MongoClient("localhost", 27017) client = pymongo.MongoClient('mongodb://localhost:27017/')

3. 获得数据库test1

db = client.test1 db = client['test']

4. 获得集合movie

collection = db.movie collection = db['movie']

5. 添加数据

#增加一条 m1={name:'300集',actor:'高总',level:10} m1_id = movie.insert_one(s1).inserted_id #增加多条 mids = movie.insert_many([movie1,movie2])

注意 :原insert方法也可以实现上面的功能,但是在PyMongo 3.x的版本已经不推荐使用了

6. 查找数据

find() 返回一个生成器对象find_one() 返回一条数据 result = movie.find_one() result = movie.find_one({'name':'300集'}) result = movie.find_one({'_id':OjectId('5932a80115c2606a59e8a049')}) result = movie.find_one({level:{$gt:1}}) results = movie.find()

比较符号

功能符号

7. 获取文档个数

count = movie.count() count = collection.find({'level': 10}).count()

8. 排序

results = collection.find().sort('name', pymongo.ASCENDING)

9. 偏移

collection.find().sort('name', pymongo.ASCENDING).skip(2).limit(2)

10. 更新

args = {"name": "曹操"} student.update_one(args, {'$set':{field:value}}}) result = collection.update_many(query, {'$set': {field:value}})

注意: 也可以实现上面的功能,但是在PyMongo 3.x的版本已经不推荐使用了

11. 删除

result = collection.remove({'name': '300集'}) #符合条件的所有数据均会被删除 result = collection.delete_one({'name': '300集'}) result = collection.delete_many({'age': {'$lt': 25}}) from pymongo import MongoClient import pymongo # 获取连接数据库对象 client = MongoClient() # 获取数据库实例 person = client.person # 获取集合 student = person.student # 操作集合 # stus = student.find() # for stu in stus: # print(stu) # print(stus.next()) # stu = student.find_one({"name":"小二"}) # print(stu) # count测试 # num = student.find().count() # print(num) # 分页测试skip, limit # stus = student.find().skip(6).limit(6) # for stu in stus: # print(stu) # 排序测试 sort # stus = student.find().sort("age", pymongo.ASCENDING) # for stu in stus: # print(stu) # 保存数据测试 # stu = {"name": "诸葛孔明", "country": "蜀国"} # student.insert(stu) # 增加数据测试 # args = {"name":"诸葛孔明"} # student.update_one(args, {"$set":{"age":30}}) # 删除数据测试 # args = {"name":"诸葛孔明"} # student.remove(args)

将爬取到的数据保存到数据库

代码:

番外-Mongodb 常用命令

1. 一般命令

显示数据库列表:show dbs 切换/创建数据库: use dabaseA (dabaseA为数据库名,如果该数据库不存在,则会创建) 删除当前数据库:db.dropDatabase() --当执行use dabaseA命令后,当前数据库就是dabaseA,所以再执行db.dropDatabase(),删除的当前数据库就是dabaseA。 显示当前数据库中的操作命令:db.help() 显示当前数据库中的集合:show collections (这里的集合类似关系数据库中的表) 显示数据库中某集合的操作命令: db.table.help() (这里的table是当前数据库中一个集合) 往某一集合中插入数据:db.person.insert({'name':'小王', 'age' : 20, 'sex':'男'}) 或者 db.person.save({'name':'小王', 'age' : 20, 'sex':'男'})

注意: mongodb的save和insert函数都可以向collection里插入数据,但两者是有两个区别:

使用save函数里,如果原来的对象不存在,那他们都可以向collection里插入数据,如果已经存在,save会调用update更新里面的记录,save则需要遍历列表,一个个插入,效率稍低 而insert则会忽略操作,insert可以一次性插入一个列表,而不用遍历,效率高 例如: ​ 已存在数据: {_id : 'abc123', " name " : " 小王 " } 再次进行插入操作时 insert({_id : 'abc123', " name " : " 小李 " }) 会报主键重复的错误提示   save({ _id : 'abc123', " name " : " 小李 " }) 会把 小王 修改为 小李 。 如果集合中不存在 _id : 'abc123',insert({_id : 'abc123', " name " : " 小李 " }) 增加一条数据save({ _id : 'abc123', " name " : " 小李 " }) 增加一条数据 查看当前使用的数据库:db 或 db.getName() 两者效果一样 显示当前数据库的状态:db.stats() 显示当前数据库的版本 :db.version() 显示当前数据库链接的地址:db.getMongo() 在指定的机器上,从数据库A,负责数据到B:db.copyDatabase("mydb", "temp", "127.0.0.1") 将本机的mydb的数据复制到temp数据库中 显示当前数据库中所有集合: db.getCollectionNames() 显示数据库的状态:db.table.stats() 删除当前数据库中某个集合:db.table.drop() 删除集合 table 删除当前数据库某个集合中的所有数据:db.table.remove({}) 删除集合 table中所有数据 删除当前数据库某个集合中name='test'的记录:db.table.remove({name:'test'}) 删除当前数据库某个集合中所有数据:db.Information.remove({})

2. 查看集合基本信息命令

查看当前数据库中某集合中的帮助:db.table.help()查看某集合的数据条数:db.table.count()查看某集合数据空间大小: db.table.dataSize() 单位是字节查看某集合的总空间大小:db.table.storageSize()

3. 查询命令

查询索引记录:相当于select * from table

db.table.find()

查询age = 22的记录

db.table.find({age:22})

查询age >22的记录

db.table.find({age:{$gt:22}}) db.table.find("this.age>22")

查询age>=22的记录

db.table.find({age:{$gte:22}}) db.table.find("this.age>=22")

查询age <30的记录

db.table.find({age:{$lt:30}}) db.table.find("this.age < 30")

查询age <=30的记录

db.table.find({age:{$lte:30}}) db.table.find("this.age<=30")

查询age >20 并且age< 30的记录

db.table.find({age:{gt:20,lt :30}}) db.table.find("this.age>20 && this.age< 30")

查询集合中name 包含mongo的数据,相当于like '%mongo%' 模糊查询

db.table.find({name:/mongo/})

查询集合中 name中以mongo开头的数据,相当于like 'mongo%' 模糊查询

db.table.find({name:/^mongo/})

查询集合中,只查询,name和age两列db.table.find({},{name:1,age:1}) 查询结合中age>10 ,并且只查询 name 和 age两列db.table.find({age:{$gt:10}},{name:1,age:1}) 按年龄排序 ``` db.table.find().sort({age:1,name:1}) 按照年龄和姓名升序 db.table.find().sort({age:-1,name:1}) 按照年龄降序,姓名升序 python db.table.find().sort(‘age‘,pymongo.ASCENDING) 或 db.table.find().sort(‘age‘,1)升序; db.table.find().sort(‘age‘,pymongo.DESCENDING) 或 db.table.find().sort(‘age‘,-1)降序 db.table.find().sort([(‘age‘,pymongo.DESCENDING),('name',pymongo.ASCENDING)]) 年龄降序,姓名升序 或 db.table.find().sort([(‘age‘,-1),('name':1)])年龄降序,姓名升序 ``` 注意mongo和python里面命令的区别是冒号,python是逗号 查询前10条数据,相当于select top 10 from tabledb.table.find().limit(10) 查询10条以后的数据,相当于 select * from table where id not in (select top * from table )db.table.find().skip(10) 查询5-10条之间的数据db.table.find().skip(5).limit(10) 查询 age =10 or age =20的记录db.table.find({$or:[{age:20},{age:30}]}) 查询age >20的记录条数db.table.find({age:{$gt:20}}).count() 查询age>30 or age <20 的记录db.table.find({or:[{age:{gt:30}},{age:{$lt:20}}]}) db.table.find("this.age>30 || this.age < 20") 查询age > 40 or name ='mike'的记录  db.table.find({or:[{age:{gt:40}},{name:'mike'}]}) 查询age > 40 or name ='mike'的记录,只查询name 和age两列,并且按照name升序,age降序db.table.find({or:[{age:{gt:40}},{name:'mike'}]},{name:1,age:-1}) 查询age > 40 并且 name ='mike'的记录,只查询name 和age两列,并且按照name升序,age降序db.table.find({and:[{age:{gt:40}},{name:'mike'}]},{name:1,age:-1}) python 代码db.table.find({'and':[{age:{'$gt':40}},{'name':'mike'}]},{'name':1,'age':-1}) 像and和字段名必须在引号内,否则报错 查询age 在[30,40] 内的记录db.table.find({age:{$in:[30,40]}}) 查询age不在[30,40]范围内的记录db.table.find({age:{$nin:[30,40]}}) 查询age能被3整除的记录db.table.find({age:{$mod:[3,0]}}) 查询age能被3整除余2的记录db.table.find({age:{$mod:[3,2]}})

//假如有以下文档 { 'name' : { 'first' : 'Joe', 'last' : 'Schmoe' } 'age' : 45 } ​

查询姓名为询姓名是Joe Schmoe的记录

``` db.table.find({'name.first':'Joe','name.last':'Schmoe'})

db.table.find({name:{first:'Joe',last:'Schmoe'}}) ```

如果需要多个元素来匹配数组,就需要使用$all了

//假设在我们表中3个下面的文档:

db.food.insert({'_id' : 1,'fruit' : ['apple', 'banana', 'peach']}) db.food.insert({'_id' : 2,'fruit' : ['apple', 'kumquat', 'orange']}) db.food.insert({'_id' : 3,'fruit' : ['cherry', 'banana', 'apple']})

要找到既有apple又有banana的文档:

db.food.find({fruit:{$all:['apple', 'banana']}}) 查询age不是30并且性别不是‘男’的记录,就用到 $nor

db.person.find({$nor:[{age:30},{sex:'男'}]})

查询age不大于30的记录,用到not,not执行逻辑NOT运算,选择出不能匹配表达式的文档 ,包括没有指定键的文档。

``` db.person.find({age:{not:{gt:30}}})

```

如果$exists的值为true,选择存在该字段的文档;若值为false则选择不包含该字段的文档。

选择age存在,且不在[30,40]只能的记录

db.person.find({age:{exists:true,nin:[30,40]}}) 查询name中包括字母t的记录,类似 name like '%t%'

``` db.person.find({name:/t/})

db.person.find({name:{$regex:/t/}})

db.person.find({name:/t/i}) i在这里是不区分大小写

db.person.find({name:{regex:/t/,options:'i'}}) i在这里是不区分大小写

```

查询name中以t字母结尾的记录,类似 name like '%t', 要用到符号$

``` db.person.find({name:/t$/})

```

如果在查询的时候需要多个元素来匹配数组,就需要用到$all了,这样就匹配一组元素。

例如:假如创建了包含3个元素的如下集合:

``` { "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 2, "fruit" : [ "apple", "pear", "orange" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

```

要找到既有apple, 又有banana的文档,就要用到$all

db.food.find({fruit:{$all:['apple','banana']}})

查询结果如下:

db.food.find({fruit:{$all:['apple','banana']}}) { "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

注意两条结果记录的apple和banana的顺序是不一样的,也就是说,顺序无关紧要。

要是想查询指定数组位置的元素,则需要用key.index语法指定下标

db.food.find({'fruit.2':'peach'}),结果为:

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }

null

null比较奇怪,它确实能匹配本身,假如有下面的数据:

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 2, "fruit" : [ "apple", "pear", "orange" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] } { "_id" : 4, "fruit" : null }

db.food.find({fruit:null}) 查询结果:

{ "_id" : 4, "fruit" : null }

但是null不仅能匹配本身,而且能匹配“不存在的” ,例如:

db.food.find({x: null}) ,food集合中本来不包含x键的,结果如下:

db.food.find({x:null})

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 2, "fruit" : [ "apple", "pear", "orange" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] } { "_id" : 4, "fruit" : null } $size 对于查询来说也是意义非凡,顾名思义就是可用它来查询指定长度的数组

比如有以下数据:

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 2, "fruit" : [ "apple", "pear", "orange" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] } { "_id" : 4, "fruit" : null } { "_id" : 5, "fruit" : [ "apple", "orange" ] }

db.food.find({fruit:{$size:3}})

查询结果如下:fruit对应的数组的长度为3

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] } { "_id" : 2, "fruit" : [ "apple", "pear", "orange" ] } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

db.food.find({fruit:{$size:1}})

查询结果如下:fruit对应的数组的长度为1

{ "_id" : 5, "fruit" : [ "apple", "orange" ] } slice 可以按偏移量返回记录,针对数组。

如{"slice":10}返回前10条,{"$slice":{[23,10]}}从24条取10条

例如在集合food中有数据如下:

{ "_id" : 1, "fruit" : [ "apple", "pear", "orange", "strawberry", "banana" ], "name" : "fruitName1" } { "_id" : 2, "fruit" : [ "apple", "orange", "pear", "banana" ], "name" : "fruitName2" } { "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ], "name" : "fruitName3" } { "_id" : 4, "fruit" : null }

针对fruit 如何只获取该键对应数据前个数据,{"$slice":2}

查询语句:db.food.find({},{fruit:{$slice:2}}) 查询结果为:

{ "_id" : 1, "fruit" : [ "apple", "pear" ], "name" : "fruitName1" } 注意fruit对应的数据,只获取了,前两个数据,后面的去掉了 { "_id" : 2, "fruit" : [ "apple", "orange" ], "name" : "fruitName2" } { "_id" : 3, "fruit" : [ "cherry", "banana" ], "name" : "fruitName3" } { "_id" : 4, "fruit" : null }

针对fruit 如何只获取该键对应数据从第二个数据开始取,取两个,{"$slice":[1,2]}

查询语句:db.food.find({},{fruit:{$slice:[1,2]}}) 查询结果为:

{ "_id" : 1, "fruit" : [ "pear", "orange" ], "name" : "fruitName1" } { "_id" : 2, "fruit" : [ "orange", "pear" ], "name" : "fruitName2" } { "_id" : 3, "fruit" : [ "banana", "apple" ], "name" : "fruitName3" } { "_id" : 4, "fruit" : null }

$elemMatch ​ 如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素。

例如数据集school中有如下数据:

``` { "_id" : 1, "zipcode" : "63109", "students" : [ { "name" : "john", "school" : 102, "age" : 10 }, { "name" : "jess", "school" : 102, "age" : 11 }, { "name" : "jeff", "school" : 108, "age" : 15 } ] } { "_id" : 2, "zipcode" : "63110", "students" : [ { "name" : "ajax", "school" : 100, "age" : 7 }, { "name" : "achilles", "school" : 100, "age" : 8 } ] } { "_id" : 3, "zipcode" : "63108", "students" : [ { "name" : "ajax", "school" : 100, "age" : 7 }, { "name" : "achilles", "school" : 100, "age" : 8 } ] } { "_id" : 4, "zipcode" : "63109", "students" : [ { "name" : "barney", "school" : 102, "age" : 7 }, { "name" : "ruth", "school" : 102, "age" : 16 } ] } { "_id" : 5, "zipcode" : "63109", "students" : [ { "name" : "barney", "school" : 102, "age" : 12 }, { "name" : "ruth", "school" : 102, "age" : 16 } ] }

```

要查询 zipcode="63109" ,school= ‘102’ 并且 age>10的记录

db.school.find( { zipcode: "63109" },{ students: { elemMatch: { school: 102 ,age:{gt: 10}} } } )

查询结果:

{ "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] } { "_id" : 4, "students" : [ { "name" : "ruth", "school" : 102, "age" : 16 } ] } { "_id" : 5, "students" : [ { "name" : "barney", "school" : 102, "age" : 12 } ] } $exists

判断某个字段是否存在,查询school集合中存在zipcode字段的记录

``` db.school.find({zipcode:{$exists:1}})

```

假如有集合school ,数据如下:

``` { "_id" : 1, "zipcode" : "63109", "students" : [ { "name" : "john", "school" : 102, "age" : 10 }, { "name" : "jess", "school" : 102, "age" : 11 }, {   "name" : "jeff", "school" : 108, "age" : 15 } ] } { "_id" : 2, "zipcode" : "63110", "students" : [ { "name" : "ajax", "school" : 100, "age" : 7 }, { "name" : "achilles", "school" : 100, "age" : 8 } ] } { "_id" : 3, "zipcode" : "63109", "students" : [ { "name" : "ajax", "school" : 100, "age" : 7 }, { "name" : "achilles", "school" : 100, "age" : 8 } ] } { "_id" : 4, "zipcode" : "63109", "students" : [ { "name" : "barney", "school" : 102, "age" : 7 }, { "name" : "ruth", "school" : 102, "age" : 16 } ] } { "_id" : 5, "zipcode" : "63109", "students" : [ { "name" : "barney", "school" : 102, "age" : 12 }, { "name" : "ruth", "school" : 102, "age" : 16 } ] }

```

如果只查询students字段里面的内容,并且只查询school =102 的姓名和年龄信息:

查询语句为: ​

`` db.school.find({'students.school':102},{'students.name':1,'students.age':1})

```

结果如下:

``` { "_id" : 1, "students" : [ { "name" : "john", "age" : 10 }, { "name" : "jess", "age" : 11 }, { "name" : "jeff", "age" : 15 } ] } { "_id" : 4, "students" : [ { "name" : "barney", "age" : 7 }, { "name" : "ruth", "age" : 16 } ] } { "_id" : 5, "students" : [ { "name" : "barney", "age" : 12 }, { "name" : "ruth", "age" : 16 } ] }

```

假设school 集合中包含一些记录:students字段对应一个数据字典

``` { "_id" : 7, "zipcode" : "63109", "students" : { "name" : "jike", "school" : "102", "age" : 45 } } { "_id" : 8, "zipcode" : "63109", "students" : { "name" : "Marry", "school" : "100", "age" : 75 } }

```

如果只查询字段students对应name和age信息,则查询语句如下:

``` db.school.find({_id:{$gt:5}},{'students.name':1,'students.age':1})

```

结果为:这里_id是必须要显示的

{ "_id" : 7, "students" : { "name" : "jike", "age" : 45 } } { "_id" : 8, "students" : { "name" : "Marry", "age" : 75 } }

最新回复(0)