文章目录
MongoDB和pymongo的使用,请从目录中直达↑
给个电梯方便别人方便自己:MongoDB,pymongo。
关于数据库的概念
MongoDB 是典型的NoSQL数据库,先看一些关系型与非关系型数据库的概念。
关系型数据库(ACID规则)
NoSQL:NoSQL = Not Only SQL ,意即"不仅仅是SQL",也就是非关系型数据库。与之相对的是RDBMS,先看RDBMS。
RDBMS:传统的数据库是关系型数据库,由**关系数据库管理系统(RDBMS)**来管理数据。。使得数据建模和应用程序编程更加简单。关系模型非常适合于客户服务器编程,是结构化数据存储在网络和商务应用的主导技术。
关系型数据库遵循ACID规则:
- A (Atomicity) 原子性:事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。
- C (Consistency) 一致性:数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。
- I (Isolation) 独立性:并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。
- D (Durability) 持久性:持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。
RDBMS vs NoSQL
RDBMS
- 高度组织化结构化数据
- 结构化查询语言(SQL) (SQL)
- 数据和关系都存储在单独的表中。
- 数据操纵语言,数据定义语言
- 严格的一致性
- 基础事务
NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言
- 没有预定义的模式
- 键 - 值对存储,列存储,文档存储,图形数据库
- 最终一致性,而非ACID属性
- 非结构化和不可预知的数据
- CAP定理
- 高性能,高可用性和可伸缩性
MongoDB是典型的非关系型、分布式、不提供ACID的数据库设计模式的数据库。
MongoDB的优点:易扩展、高性能、灵活的数据模型
MongoDB的缺点:数据重复存储,占用空间大
sql与mongodb的区别
SQL术语 | MongoDB | 解释 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
MongoDB概念
- MongoDB中的数据存储是以Bson的形式存储的,Bson是二进制的json,所以看上去记录的形式类似于json数据
- MongoDB中集合中的数据不同于关系型数据库中的数据,MongoDB中文档结构可以不同,因此扩展性非常好
MongoDB中的三要素:数据库 > 集合 > 文档
数据库
一个mongodb中可以建立多个数据库。
MongoDB的默认数据库为"db",该数据库存储在data目录中。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
数据库通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串。
- 不能是空字符串("")。
- 不得含有’ '(空格)、.、$、/、\和\0 (空字符)。
- 应全部小写。
- 最多64字节。
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
- admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
- local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
集合
集合是一组MongoDB的文档。它相当于一个RDBMS表。收集存在于一个单一的数据库。集合不执行模式。集合内的文档可以有不同的领域。通常情况下,一个集合中的所有文件是相同或相关的目的。
MongoDB 中的集合类似 SQL 的表。
文档
文档是一组键 - 值对。文件动态模式。动态模式是指,在相同集合中的文档不需要具有相同的字段或结构组的公共字段的集合的文档,可以容纳不同类型的数据。
MongoDB 中的一个文档类似 SQL 表中的一条记录。
MongoDB的使用
启动MongoDB
命令行(终端)启动命令
$ mongod
: 运行服务端
$ mongo
: 启动客户端
查看帮助命令,默认端口,日志位置
查看帮助:
mongod –help
查看是否启动成功:ps ajx|grep mongod
默认端⼝:27017
日志的位置:/var/log/mongodb/mongod.log
mongodb客户端
启动本地客户端:
mongo
查看帮助:mongo –help
退出:exit
或者ctrl+c
MongoDB基础命令
操作数据库命令
查看当前的数据库:
db
查看所有的数据库:show dbs
/show databases
切换数据库:use db_name
切换到没有的数据库, 添加数据时会自动创建
删除当前使用的数据库:db.dropDatabase()
显示当前数据库状态:db.stats()
当前数据库版本:db.version()
查看当前数据库的链接机器地址:db.getMongo()
$ ./mongo
MongoDB shell version: 3.0.6
connecting to: myTest
>show dbs #显示所有数据的列表。
local 0.078GB
myTest 0.078GB
>db #显示当前数据库对象或集合。
myTest
> use local #连接到一个指定的数据库local。
switched to db local
> db
local
>
操作集合的命令
创建用户:
db.createUser({user:"laowang",pwd:"123456",roles:[{role:"userAdmin",db:"stu"}]})
创建集合:
- 不手动创建集合:向不存在的集合中第1次加数据时,集合将会自动创建
- 手动创建:
db.createCollection(name,options) db.createCollection("stu") db.createCollection("sub", { capped : true, size : 10 } )
参数capped:默认值为false表示不设置上限,值为true表示设置上限
参数size:当capped值为true时,需要指定此参数,表示上限值,单位为字节。当集合达到上限时,会将最早写入的数据覆盖。
显示当前所有用户:
show users
删除用户:db.removeUser("userName")
查看集合:show collections
删除集合:db.collectionName.drop()
参数字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | 固定集合的大小,如果值为true时必须也指定size |
autoindexid | 布尔 | 如果为true,自动创建_id字段索引 |
size | 数值 | 设置集合的大小 |
max | 数值 | 指定固定集合中包含文档的最大数量 |
mongo中的数据类型
String : 这是最常用的数据类型来存储数据。在MongoDB中的字符串必须是有效的UTF-8。
Integer : 这种类型是用来存储一个数值。整数可以是32位或64位,这取决于您的服务器。
Boolean : 此类型用于存储一个布尔值 (true/ false) 。
Double : 这种类型是用来存储浮点值。
Min/ Max keys : 这种类型被用来对BSON元素的最低和最高值比较。
Arrays : 使用此类型的数组或列表或多个值存储到一个键。
Timestamp : 时间戳,表示从1970-1-1到现在的总秒数。用于记录文件被修改或添加的时间。
Object : 此数据类型用于嵌入式的文件。
Null : 这种类型是用来存储一个Null值。
Symbol : 此数据类型用于字符串相同,但它通常是保留给特定符号类型的语言使用。
Date : 此数据类型用于存储当前日期或时间的UNIX时间格式。用于指定自己的日期YYYY-MM-DD
到创建对象。new Date('2017-12-20')
Binary data : 此数据类型用于存储二进制数据。
Code : 此数据类型用于存储到文档中的JavaScript代码。
Regular expression : 此数据类型用于存储正则表达式
Object ID : 此数据类型用于存储文档的ID。是每个文档必有的一个属性,保证每个文档的唯一性。[objectID是个12字节的十六进制数(了解):前4个字节为当前时间戳,接下来3个字节的机器ID,接下来的2个字节中MongoDB的服务进程id,最后3个字节是简单的增量值。]
语法提示help
输入help可以看到基本操作命令:
db.help()
:显示数据库操作命令,里面有很多的命令
db.foo.help()
:显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令
pymongo常用命令
连接 & 创建
创建数据库需要先使用 MongoClient 对象连接服务器,并且指定连接的 URL 地址和要创建的数据库名。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["mydb"]
# 在 MongoDB 中,数据库只有在内容插入后才会创建! 就是说,数据库创建后要创建集合(数据表)并插入一个文档(记录),数据库才会真正创建。
另一种格式:
from pymongo import MongoClient
myclient = MongoClient('localhost', 27017) #创建本地连接,localhost指本地连接
db = myclient.face_recog #连接face_recog数据库,没有则自动创建
face_data = db.facial_features #使用facial_features集合,没有则自动创建
读取 MongoDB 中的所有数据库list_database_names()
,并判断指定的数据库是否存在:
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient('mongodb://localhost:27017/')
dblist = myclient.list_database_names()
# dblist = myclient.database_names()
if "mydb" in dblist:
print("数据库mydb已存在!")
#注意:database_names 在最新版本的 Python 中已废弃,Python3.7+ 之后的版本改为了 list_database_names()。
MongoDB 使用数据库对象来创建集合,实例如下:
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
#在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。
读取 MongoDB 数据库中的所有集合list_collection_names()
,并判断指定的集合是否存在:
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient('mongodb://localhost:27017/')
mydb = myclient['runoobdb']
collist = mydb. list_collection_names()
# collist = mydb.collection_names()
if "sites" in collist: # 判断 sites 集合是否存在
print("集合已存在!")
#注意:collection_names 在最新版本的 Python 中已废弃,Python3.7+ 之后的版本改为了 list_collection_names()。
对数据库做数据处理的常用命令包括增删改查,对应到mongoDB的操作为:插入、删除、更新、查询。具体使用如下:
插入
插入单个文档
集合中插入文档使用 insert_one()
方法,该方法的第一参数是字典格式的键值对。
insert_one()
方法返回 InsertOneResult 对象,该对象包含 inserted_id 属性,它是插入文档的 id 值。
如果我们在插入文档时没有指定 _id,MongoDB 会为每个文档添加一个唯一的 id。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
mydict = { "name": "RUNOOB", "alexa": "10000", "url": "https://www.runoob.com" }
x = mycol.insert_one(mydict)
print(x)
#输出:<pymongo.results.InsertOneResult object at 0x10a34b288>
print(x.inserted_id)
#输出:5b2369cac315325f3698a1cf
插入多个文档
集合中插入多个文档使用 insert_many()
方法,该方法的第一参数是字典列表。
insert_many() 方法返回 InsertManyResult 对象,该对象包含 inserted_ids 属性,该属性保存着所有插入文档的 id 值。
执行完以上插入操作,可以在命令终端用查询方法db.collection.find()
,查看数据是否已插入。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
mylist = [
{ "name": "Taobao", "alexa": "100", "url": "https://www.taobao.com" },
{ "name": "QQ", "alexa": "101", "url": "https://www.qq.com" },
{ "name": "Facebook", "alexa": "10", "url": "https://www.facebook.com" },
{ "name": "知乎", "alexa": "103", "url": "https://www.zhihu.com" },
{ "name": "Github", "alexa": "109", "url": "https://www.github.com" }
]
x = mycol.insert_many(mylist)
# 输出插入的所有文档对应的 _id 值
print(x.inserted_ids)
插入指定 _id 的多个文档 :
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["site2"]
mylist = [
{ "_id": 1, "name": "RUNOOB", "cn_name": "菜鸟教程"},
{ "_id": 2, "name": "Google", "address": "Google 搜索"},
{ "_id": 3, "name": "Facebook", "address": "脸书"},
{ "_id": 4, "name": "Taobao", "address": "淘宝"},
{ "_id": 5, "name": "Zhihu", "address": "知乎"}
]
x = mycol.insert_many(mylist)
# 输出插入的所有文档对应的 _id 值
print(x.inserted_ids)
#输出:[1, 2, 3, 4, 5]
查询
db.foo.find()
:对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据)
db.foo.find( { a : 1 } )
:对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1.
MongoDB 中使用了 find
和 find_one
方法来查询集合中的数据,它类似于 SQL 中的 SELECT
语句。
查询集合中的一条数据:使用 find_one()
方法。
查询集合中的所有数据:find() 方法,类似 SQL 中的 SELECT * 操作。
查询指定字段的数据:使用find()
方法。
根据指定条件查询:在find()
中设置参数来过滤数据。
高级查询:查询的条件语句中,可以使用修饰符,还可以使用正则表达式作为修饰符,正则表达式修饰符只用于搜索字符串的字段。
返回指定条数记录:使用limit()
方法对查询结果设置指定条数的记录,该方法只接受一个数字参数。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
#查询集合中的一条数据
x = mycol.find_one()
print(x)
#打印集合中的所有数据
for x in mycol.find():
print(x)
#查询指定字段的数据
for x in mycol.find({},{ "_id": 0, "name": 1, "alexa": 1 }):
print(x)
#查找 address 字段为 "Park Lane 38" 的数据:
myquery = { "name": "RUNOOB" }
mydoc = mycol.find(myquery)
for x in mydoc:
print(x)
#读取 name 字段中第一个字母 ASCII 值大于 "H" 的数据,大于的修饰符条件为 {"$gt": "H"} :
myquery = { "name": { "$gt": "H" } }
mydoc = mycol.find(myquery)
for x in mydoc:
print(x)
#读取 name 字段中第一个字母为 "R" 的数据,正则表达式修饰符条件为 {"$regex": "^R"} :
myquery = { "name": { "$regex": "^R" } }
mydoc = mycol.find(myquery)
for x in mydoc:
print(x)
#返回 3 条文档记录
myresult = mycol.find().limit(3)
# 输出结果
for x in myresult:
print(x)
更新
修改文档中的记录:使用update_one()
方法。如果查找到的匹配数据多余一条,则只会修改第一条。该方法第一个参数为查询的条件,第二个参数为要修改的字段。
修改所有匹配到的记录:使用 update_many()
。参数同上。
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
myquery = { "alexa": "10000" }
newvalues = { "$set": { "alexa": "12345" } }
#修改匹配到的第一个结果,将 alexa 字段的值 10000 改为 12345
mycol.update_one(myquery, newvalues)
# 输出修改后的 "sites" 集合
for x in mycol.find():
print(x)
#查找所有以 F 开头的 name 字段,并将匹配到所有记录的 alexa 字段修改为 123
myquery = { "name": { "$regex": "^F" } }
newvalues = { "$set": { "alexa": "123" } }
x = mycol.update_many(myquery, newvalues)
print(x.modified_count, "文档已修改")
删除
删除一个文档:使用delete_one()
方法,该方法第一个参数为查询对象,指定要删除哪些数据。
删除多个文档:使用delete_many()
方法,该方法第一个参数为查询对象,指定要删除哪些数据。
删除集合中的所有文档:delete_many()
方法如果传入的是一个空的查询对象,则会删除集合中的所有文档。
删除集合:使用 drop()
方法来删除一个集合。如果删除成功 drop()
返回 True
,如果删除失败(集合不存在)则返回 false
。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
myquery = { "name": "Taobao" }
mycol.delete_one(myquery)
# 删除后输出
for x in mycol.find():
print(x)
#删除所有 name 字段中以 F 开头的文档
myquery = { "name": {"$regex": "^F"} }
x = mycol.delete_many(myquery)
print(x.deleted_count, "个文档已删除")
#删除集合中的所有文档
x = mycol.delete_many({})
print(x.deleted_count, "个文档已删除")
#删除集合
mycol.drop()
排序
sort()
方法可以指定升序或降序排序。
第一个参数为要排序的字段,第二个字段指定排序规则,1 为升序,-1 为降序,默认为升序。
#!/usr/bin/python3
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"]
mycol = mydb["sites"]
#按升序排序
mydoc = mycol.find().sort("alexa")
for x in mydoc:
print(x)
#按降序排序
mydoc = mycol.find().sort("alexa", -1)
for x in mydoc:
print(x)
参见pymongo官方文档:PyMongo 3.7.2 documentation » API Documentation »
参考链接:
http://api.mongodb.com/python/current/api/pymongo/
http://www.cnblogs.com/longguoliang/p/9501597.html
https://blog.youkuaiyun.com/cartoonjh/article/details/79559958
http://www.runoob.com/python3/python-mongodb.html