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 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,例如:

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

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

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

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

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

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

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

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

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

  1. 数据库事务一致性需求

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

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

  1. 对复杂的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 特点
  1. 它可以处理超大量的数据

  2. 它运行在便宜的 PC 服务器集群上 PC

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

  1. 它击碎了性能瓶颈

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

  1. 它没有过多的操作

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

  1. 它的支持者源于社区

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

2.5 MongoDB 特点

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

  1. 面向集合(Collenction-Orented)

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

  1. 模式自由(schema-free)

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

  1. 文档型

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

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

  1. 特点
  • 面向集合存储,易于存储对象类型的数据
  • 模式自由
  • 支持动态查询
  • 支持完全索引,包含内部对象
  • 支持查询
  • 支持复制和故障恢复
  • 使用高效的二进制数据存储,包括大型对象(如视频等)
  • 自动处理碎片,以支持云计算层次的扩展性
  • 支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++语言的驱动程序,社区
  • 中也提供了对 Erlang 及.NET 等平台的驱动程序
  • 文件存储格式为 BSON(一种 JSON 的扩展)
  • 可通过网络访问
  1. 功能
  • 面向集合的存储:适合存储对象及 JSON 形式的数据

  • 动态查询:MongoDB 支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易

  • 查询文档中内嵌的对象及数组

  • 完整的索引支持:包括文档内嵌对象及数组。MongoDB 的查询优化器会分析查询表达式,并生成一个高效的查询计划

  • 查询监视:MongoDB 包含一系列监视工具用于分析数据库操作的性能

  • 复制及自动故障转移:MongoDB 数据库支持服务器之间的数据复制,支持主-从模式及

  • 服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移

  • 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)

  • 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器

  1. 适用场合
  • 网站数据:MongoDB 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
  • 缓存:由于性能很高,MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后,由 MongoDB 搭建的持久化缓存层可以避免下层的数据源过载
  • 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储
  • 高伸缩性的场景:MongoDB 非常适合由数十或数百台服务器组成的数据库。MongoDB的路线图中已经包含对 MapReduce 引擎的内置支持
  • 用于对象及 JSON 数据的存储:MongoDB 的 BSON 数据格式非常适合文档化格式的存储及查询
3. MongoDB 下载

mongodb官网

https://www.mongodb.com/download-center#community

https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.0.6-signed.msi

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管理工具,轻量级, 支持多国语言

1. 启动mongodb

  1. 创建数据库目录, 如 /data/db ,

  2. mongod --dbpath d:/data/db

  3. mongodb要求磁盘剩余空间>=4G,如果不够,可以用 --smallfiles 选项

2. MongoDB 与 Sql的概念对比

SQLMongoDB
databasedatabase
tablecollection
rowdocument or BSON document
colunmfield
indexindex
primary key_id (auto set)

3. 数据类型

MongoDB中常用的几种数据类型

类型名称
Object ID文档ID
String字符串,最常用,必须是有效的UTF-8
Boolean存储一个布尔值,true或false
Integer整数可以是32位或64位,这取决于服务器
Double存储浮点值
Arrays数组或列表,多个值存储到一个键
Object用于嵌入式的文档,即一个值为一个文档
Null存储Null值
Timestamp时间戳
Date存储当前日期或时间的UNIX时间格式
3.1 Object ID
  • 每个文档都有一个属性,为_id,保证每个文档的唯一性
  • 可以自己去设置_id插入文档
  • 如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectID
  • objectID是一个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
idtitlecontent
1天气万里无云
2心情呵呵哒
特点:
  1. 有结构
  2. 行遵循结构
5.2 collenction
{id:1,title:'晴空万里'}
{id:2,title:'额...',data:'2018'}
特点:
  1. collection无结构
  2. 文档相互独立,没有固定结构

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

1 数据的操作

1.1 数据的增加

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

1.1.1 insert

而insert则会忽略操作,insert可以一次性插入一个列表,而不用遍历,效率高

db.集合名称.insert(document)
1.1.2 save

使用save函数里,如果原来的对象不存在,那他们都可以向collection里插入数据,如果已经存在,save会调用update更新里面的记录,save则需要遍历列表,一个个插入,效率稍低

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()

1. Mongo的简单查询

1.1 find

查找到所有匹配数据

db.集合名.find({条件文档})
1.2 findOne

只返回匹配的第一个数据

db.集合名.findOne({条件文档})

2. 运算符

语法操作格式
$eq等于{:}
$lt小于{:{$lt:}}
$lte小于或等于{:{$lte:}}
$gt大于{:{$gt:}}
$gte大于或等于{:{$gte:}}
$ne不等于{:{$ne:}}
$or{$or:[{},{}]}
$in在范围内{age:{$in:[val1,val2]}}
$nin不在范围内{age:{$nin:[val1,val2]}}
举例
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为降序排列

6 .count

用于统计结果集中文档条数

db.集合名称.find({条件}).count()

安装环境

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()

比较符号

符号含义示例
$lt小于{‘age’: {’$lt’: 20}}
$gt大于{‘age’: {’$gt’: 20}}
$lte小于等于{‘age’: {’$lte’: 20}}
$gte大于等于{‘age’: {’$gte’: 20}}
$ne不等于{‘age’: {’$ne’: 20}}
$in在范围内{‘age’: {’$in’: [20, 23]}}
$nin不在范围内{‘age’: {’$nin’: [20, 23]}}

功能符号

符号含义示例示例含义
$regex匹配正则表达式{‘name’: {’$regex’: ‘^M.*’}}name以M开头
$exists属性是否存在{‘name’: {’$exists’: True}}name属性存在
$type类型判断{‘age’: {’$type’: ‘int’}}age的类型为int
$mod数字模操作{‘age’: {’$mod’: [5, 0]}}年龄模5余0
$text文本查询{‘KaTeX parse error: Expected '}', got 'EOF' at end of input: text': {'search’: ‘Mike’}}text类型的属性中包含Mike字符串
$where高级条件查询{’$where’: ‘obj.fans_count == obj.follows_count’}自身粉丝数等于关注数
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. 更新
condition = {'name': '300集'}
movie = collection.find_one(condition)
movie['level'] = 8
result = collection.update_one(condition, movie)
result = collection.update_many(condition, {'$set': movie})

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

11. 删除
result = collection.remove({'name': '300集'}) #符合条件的所有数据均会被删除
result = collection.delete_one({'name': '300集'})
result = collection.delete_many({'age': {'$lt': 25}})

1. 一般命令

  1. 显示数据库列表:show dbs

  2. 切换/创建数据库: use dabaseA (dabaseA为数据库名,如果该数据库不存在,则会创建)

  3. 删除当前数据库:db.dropDatabase() --当执行use dabaseA命令后,当前数据库就是dabaseA,所以再执行db.dropDatabase(),删除的当前数据库就是dabaseA。

  4. 显示当前数据库中的操作命令:db.help()

  5. 显示当前数据库中的集合:show collections (这里的集合类似关系数据库中的表)

  6. 显示数据库中某集合的操作命令: db.table.help() (这里的table是当前数据库中一个集合)

  7. 往某一集合中插入数据: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 " : " 小李 " }) 增加一条数据

  1. 查看当前使用的数据库:dbdb.getName() 两者效果一样

  2. 显示当前数据库的状态:db.stats()

  3. 显示当前数据库的版本 :db.version()

  4. 显示当前数据库链接的地址:db.getMongo()

  5. 在指定的机器上,从数据库A,负责数据到B:db.copyDatabase("mydb", "temp", "127.0.0.1") 将本机的mydb的数据复制到temp数据库中

  6. 显示当前数据库中所有集合: db.getCollectionNames()

  7. 显示数据库的状态:db.table.stats()

  8. 删除当前数据库中某个集合:db.table.drop() 删除集合 table

  9. 删除当前数据库某个集合中的所有数据:db.table.remove({}) 删除集合 table中所有数据

  10. 删除当前数据库某个集合中name='test'的记录:db.table.remove({name:'test'})

  11. 删除当前数据库某个集合中所有数据:db.Information.remove({})

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

  1. 查看当前数据库中某集合中的帮助:db.table.help()

  2. 查看某集合的数据条数:db.table.count()

  3. 查看某集合数据空间大小: db.table.dataSize() 单位是字节

  4. 查看某集合的总空间大小:db.table.storageSize()

3. 查询命令

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

db.table.find()

  1. 查询age = 22的记录

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

  1. 查询age >22的记录

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

  1. 查询age>=22的记录

db.table.find({age:{$gte:22}})
db.table.find(“this.age>=22”)
5. 查询age <30的记录

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

  1. 查询age <=30的记录

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

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

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

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

db.table.find({name:/mongo/})
9. 查询集合中 name中以mongo开头的数据,相当于like ‘mongo%’ 模糊查询

db.table.find({name:/^mongo/})
10. 查询集合中,只查询,name和age两列

db.table.find({},{name:1,age:1})
11. 查询结合中age>10 ,并且只查询 name 和 age两列

db.table.find({age:{$gt:10}},{name:1,age:1})
12. 按年龄排序

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是逗号

  1. 查询前10条数据,相当于select top 10 from table

db.table.find().limit(10)

  1. 查询10条以后的数据,相当于 select * from table where id not in (select top * from table )

db.table.find().skip(10)

  1. 查询5-10条之间的数据

db.table.find().skip(5).limit(10)

  1. 查询 age =10 or age =20的记录

db.table.find({$or:[{age:20},{age:30}]})

  1. 查询age >20的记录条数

db.table.find({age:{$gt:20}}).count()

  1. 查询age>30 or age <20 的记录

db.table.find({or:[{age:{gt:30}},{age:{$lt:20}}]})
db.table.find(“this.age>30 || this.age < 20”)

  1. 查询age > 40 or name ='mike’的记录

db.table.find({or:[{age:{gt:40}},{name:‘mike’}]})

  1. 查询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和字段名必须在引号内,否则报错

  1. 查询age 在[30,40] 内的记录

db.table.find({age:{$in:[30,40]}})

  1. 查询age不在[30,40]范围内的记录

db.table.find({age:{$nin:[30,40]}})

  1. 查询age能被3整除的记录

db.table.find({age:{$mod:[3,0]}})

  1. 查询age能被3整除余2的记录

db.table.find({age:{$mod:[3,2]}})

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

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

db.table.find({‘name.first’:‘Joe’,‘name.last’:‘Schmoe’})

db.table.find({name:{first:‘Joe’,last:‘Schmoe’}})

  1. 如果需要多个元素来匹配数组,就需要使用$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’]}})

  1. 查询age不是30并且性别不是‘男’的记录,就用到 $nor

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

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

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

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

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

db.person.find({age:{exists:true,nin:[30,40]}})

  1. 查询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在这里是不区分大小写

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

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

  1. 如果在查询的时候需要多个元素来匹配数组,就需要用到$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” ] }

  1. 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 }

  1. $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” ] }

  1. 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 }

  1. $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 } ] }

  1. $exists

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

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

  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 } }

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐