MongoDB
MongoDB的效率介于redis与mysql之间。
严格意义上来说,MongoDB既不属于关系型数据库,也不属于非关系型数据库。界内大多数人的观点认为MongoDB是一个非关系型数据库。MongoDB又称为对象存储数据库,也就是说,在MongoDB中,数据的存储都是通过对象的形式来进行读取。
常用命令
运算符
与:{$and:[{key1,value1}, {key2, value2}, …]}
或:{$or:[{key1,value1}, {key2, value2}, …]}
大于:gt (前面加上$)
大于等于:gte
小于:lt
不等于:ne
正则查询(可用于实现模糊查询):/正则运算式/
应用见 文档操作/查询文档数据
数据库操作
查看数据库
show databases/show dbs
> show databases
admin 0.000GB
config 0.000GB
local 0.000GB
创建数据库
use XXX
该命令优先失去选择使用一个数据库,如果需要use的数据库不存在,那么就新建一个。
当使用use来新建一个数据库的时候,use命令结果,并不会真正意义上的创建好一个数据库。只有在数据库中插入了一条新数据之后,这个数据库才会真正意义上的创建,并能够去进行查询操作。
> use test
switched to db test
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB # 可以发现这时候没有添加上去
> db.createCollection('hello')
{ "ok" : 1 }
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB # 创建新的集合后就添加上去了
删除当前使用的数据库
db.dropDatabase()
首先要选择中一个使用的数据库,如果是刚连接进来的时候(就不要去进行删除操作),会默认删除默认数据库。默认库里面可能会存在相关的一些配置,所以尽量不要刚连接的时候就直接进行删除操作。
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> db.dropDatabase()
{ "ok" : 1 }
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
查看当前使用的数据库
db
> db
test
集合操作
集合并不是MongoDB中独立的一个数据类型,而是用于存放数据的对象在MongoDB中统称为集合。
固定集合:
当集合被定义之后,插入到固定集合中的数据,必须满足固定集合设定的标准,包括在进行修改的时候,也需要满足固定集合设定的标准长度、类型等配置来进行存取修改。
非固定集合:
即与固定集合相反,只要插入的数据没有超过Mongo配置的默认规范,就不会出现无法插入的情况,也就是说插入的数据长度、类型等可以修改。
创建集合
db.createCollection(name,options)
参数说明:
name:要创建的集合名称
options:可选参数,指定有关内存大小及索引的选项
options可选参数如下:
字段 类型 描述 capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合, 当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 size 数值 (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 max 数值 (可选)指定固定集合中包含文档的最大数量。
Mongo中,在花括号{}中要使用到的键名可以不添加引号。
> db.createCollection('students')
{ "ok" : 1 }
> db.createCollection('teachers')
{ "ok" : 1 }
> db.createCollection('courses', {capped:true, size:4, max:3})
{ "ok" : 1 }
删除集合
db.[collection].drop()
collection是创建的集合的名字
> db.teachers.drop()
true
> db.courses.drop()
true
> show tables
students
# 如果db中的集合被删除完了,那么show dbs就不会显示该数据库,但是该db还是在缓存中,并没有被完全删除
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> db.courses.drop()
true
> db.teachers.drop()
true
> db.students.drop()
true
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
查看当前数据库中的集合
show tables
> show tables
courses
students
teachers
文档操作
在Mongo中是以文档来进行称呼每一条数据记录。
插入文档
db.collection.save(): 如果_id主键存在则更新数据,如果不存在就插入数据。该方法新版本中以废弃,可以使用db.collection.insertOne()或db.collection.replaceOne()来代替。
db.collection.insert(document,options): 若插入的数据主键已经存在,则会抛出org.springframework.dao.DuplicateKeyException异常,提示主键修复,不保存当前数据。
参数说明:
document:要插入的文档
options:可选参数,指定有关内存大小及索引的选项
options可选参数如下:
字段 类型 描述 writeconcern 数值(1/0) (可选)字段默认为1,表示要求需要去确认写的操作,0表示不要求 ordered 布尔 (可选)当其为true表示按照顺序进行写入,反之则无序。(不过没试出来怎么个排序法) **db.collection.insertOne():**插入一条数据
**db.collection.insertMany([document1,document2…]):**插入多条数据
> db.students.save({name:'keduoli'})
WriteResult({ "nInserted" : 1 })
> db.students.insert({name:'naifulian'})
WriteResult({ "nInserted" : 1 })
> db.students.insert([{_id:6, name:'aiseya',age:16}, {_id:5, name:'naifulian', age:14}], {ordered:true})
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.students.insertOne({name:'aiseya'})
{
"acknowledged" : true,
"insertedId" : ObjectId("62850dff7394c6dfcf657354")
}
> db.students.insertMany([{name:'tiyate'},{name:'latixu'}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("62850ea97394c6dfcf657355"),
ObjectId("62850ea97394c6dfcf657356")
]
}
# 固定集合
> db.courses.insert([{name:'c'}, {name:'python'}])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.courses.insert([{name:'c++'}, {name:'golang'}])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.courses.find()
{ "_id" : ObjectId("628519db7394c6dfcf65735d"), "name" : "python" }
{ "_id" : ObjectId("628519e87394c6dfcf65735e"), "name" : "c++" }
{ "_id" : ObjectId("628519e87394c6dfcf65735f"), "name" : "golang" } # 可以看到插入了四条,但因为限制是三条,所以有一条就被覆盖了。
# 带条件的查询
> db.teachers.find() # 所有数据
{ "_id" : ObjectId("62851fa17394c6dfcf657386"), "name" : "weilian", "age" : 32, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf657387"), "name" : "nigelan", "age" : 32, "sex" : "women" }
{ "_id" : ObjectId("62851fa17394c6dfcf657388"), "name" : "gelike", "age" : 40, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf657389"), "name" : "weilian", "age" : 33, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf65738a"), "name" : "nigelan", "age" : 33, "sex" : "women" }
{ "_id" : ObjectId("62851fa17394c6dfcf65738b"), "name" : "gelike", "age" : 41, "sex" : "men" }
# name为gelike或weilian并且age大于33的数据
> db.teachers.find({$and:[{$or:[{name:'weilian'}, {name:'gelike'}]}, {age:{$gte:33}}]})
{ "_id" : ObjectId("62851fa17394c6dfcf657388"), "name" : "gelike", "age" : 40, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf657389"), "name" : "weilian", "age" : 33, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf65738b"), "name" : "gelike", "age" : 41, "sex" : "men" }
# 模糊查询(通过正则实现)
# name包含li的
> db.teachers.find({name:/li/})
{ "_id" : ObjectId("62851fa17394c6dfcf657386"), "name" : "weilian", "age" : 32, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf657388"), "name" : "gelike", "age" : 40, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf657389"), "name" : "weilian", "age" : 33, "sex" : "men" }
{ "_id" : ObjectId("62851fa17394c6dfcf65738b"), "name" : "gelike", "age" : 41, "sex" : "men" }
查询文档数据
**db.collection.find(query, projection):**查询当前数据库某个集合中的所有文档
参数说明:
query:可选,使用查询操作福指定查询条件
projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需要省略该参数即可(默认省略)
**db.collcetions.findOne():**返回查询的第一个文档
**db.collection.find().pretty():**以易读的方式来读取数据
pretty()方法以格式化的方式来显示所有文档
> db.courses.find()
{ "_id" : ObjectId("62851a757394c6dfcf657365"), "name" : "golang" }
{ "_id" : ObjectId("62851a797394c6dfcf657366"), "name" : "c" }
{ "_id" : ObjectId("62851a797394c6dfcf657367"), "name" : "python" }
更新文档
db.collection.update(query,update,{upsert: boolean,multi:boolean,writeConcern:document})
update()方法用于更新已存在的文档。
参数说明:
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如 , , ,inc…)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
如果要只修改其中一个键值对,不去改动其他键值对的时候应如下进行编写:
db.collection.update(query,{$set:{key1:value}})
db.collection.save(document,{writeConcern:document})
save() 方法修改文档需要传入的文档参数有id(未指定id是插入操作)。通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。
参数说明:
document : 文档数据。
writeConcern :可选,抛出异常的级别。
> db.teachers.find() # 原来的文档内容
{ "_id" : ObjectId("62851c0e7394c6dfcf65736e"), "name" : "weilian", "age" : 32, "sex" : "men" }
{ "_id" : ObjectId("62851c0e7394c6dfcf65736f"), "name" : "nigelan", "age" : 32, "sex" : "women" }
{ "_id" : ObjectId("62851c0e7394c6dfcf657370"), "name" : "gelike", "age" : 40, "sex" : "men" }
# 覆盖
> db.teachers.update({age:32}, {ischange:true}, {upsert:true})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.teachers.find()
{ "_id" : ObjectId("62851c0e7394c6dfcf65736e"), "ischange" : true }
{ "_id" : ObjectId("62851c0e7394c6dfcf65736f"), "name" : "nigelan", "age" : 32, "sex" : "women" }
{ "_id" : ObjectId("62851c0e7394c6dfcf657370"), "name" : "gelike", "age" : 40, "sex" : "men" }
# 使用$符号修改
> db.teachers.update({age:32}, {$set:{age:33, fullOf:'keduoli'}}, {multi:true})
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.teachers.find()
{ "_id" : ObjectId("62851cdc7394c6dfcf657374"), "name" : "weilian", "age" : 33, "sex" : "men", "fullOf" : "keduoli" }
{ "_id" : ObjectId("62851cdc7394c6dfcf657375"), "name" : "nigelan", "age" : 33, "sex" : "women", "fullOf" : "keduoli" }
{ "_id" : ObjectId("62851cdc7394c6dfcf657376"), "name" : "gelike", "age" : 40, "sex" : "men" }
# save,类似于覆盖。没有则会增加
> db.teachers.find()
{ "_id" : ObjectId("62851cdc7394c6dfcf657374"), "age" : 34 }
{ "_id" : ObjectId("62851cdc7394c6dfcf657375"), "name" : "nigelan", "age" : 33, "sex" : "women"}
{ "_id" : ObjectId("62851cdc7394c6dfcf657376"), "name" : "gelike", "age" : 40, "sex" : "men" }
# 固定集合
> db.courses.find() # 原先的文档内容
{ "_id" : ObjectId("62851a757394c6dfcf657365"), "name" : "golang" }
{ "_id" : ObjectId("62851a797394c6dfcf657366"), "name" : "c" }
{ "_id" : ObjectId("62851a797394c6dfcf657367"), "name" : "python" }
> db.courses.update({name:'c'}, {name:'c++'})
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 10003,
"errmsg" : "Cannot change the size of a document in a capped collection: 34 != 36"
}
}) # 长度不一样,插入失败
> db.courses.update({name:'c'}, {age:'c+'})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.courses.find()
{ "_id" : ObjectId("62851a757394c6dfcf657365"), "name" : "golang" }
{ "_id" : ObjectId("62851a797394c6dfcf657366"), "age" : "c+" }
{ "_id" : ObjectId("62851a797394c6dfcf657367"), "name" : "python" } # 键的长度也算,总和长度不变即可
删除文档
db.collection.remove(query,{justOne:Boolean,writeConcern:document})
remove() 函数是用来移除集合中的数据。
参数说明:
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
> db.teachers.find()
{ "_id" : ObjectId("62851aea7394c6dfcf657368"), "name" : "weilian", "age" : 32, "sex" : "men" }
{ "_id" : ObjectId("62851aea7394c6dfcf657369"), "name" : "nigelan", "age" : 32, "sex" : "women" }
{ "_id" : ObjectId("62851aea7394c6dfcf65736a"), "name" : "gelike", "age" : 40, "sex" : "men" }
> db.teachers.remove({age:32}, {justOne:true})
WriteResult({ "nRemoved" : 1 })
> db.teachers.find()
{ "_id" : ObjectId("62851aea7394c6dfcf657369"), "name" : "nigelan", "age" : 32, "sex" : "women" }
{ "_id" : ObjectId("62851aea7394c6dfcf65736a"), "name" : "gelike", "age" : 40, "sex" : "men" }
# 固定集合
> db.courses.find()
{ "_id" : ObjectId("62851a757394c6dfcf657365"), "name" : "golang" }
{ "_id" : ObjectId("62851a797394c6dfcf657366"), "age" : "c+" }
{ "_id" : ObjectId("62851a797394c6dfcf657367"), "name" : "python" }
> db.courses.remove({age:'c+'})
WriteResult({
"nRemoved" : 0,
"writeError" : {
"code" : 136,
"errmsg" : "CollectionScan died due to position in capped collection being deleted. Last seen record id: RecordId(11)"
}
})
> db.courses.find()
{ "_id" : ObjectId("62851a757394c6dfcf657365"), "name" : "golang" }
{ "_id" : ObjectId("62851a797394c6dfcf657367"), "name" : "python" } # 给出了提示,但还是删除了
pymongo的使用
安装
pip install pymongo
简单使用
conn = pymongo.MongoClient('mongodb://localhost:27017') # 建立与mongo的连接
# mydb = conn.get_database() # 选择使用哪个数据库(但是数据库需要先存在)
mydb = conn['test'] # 选择要使用的数据库,如果没有则创建,此时是通过连接对象来创建或选择
myset = mydb['testset'] # 选择集合,如果没有则创建,通过数据库db对象来创建或选择。
# 但是上述的创建没有真正意义上的创建,需要插入文档之后才会真正的创建
上面代码运行后:
> show tables
courses
students
teachers
插入
myset.insert_one({'note': 'hello'})
myset.insert_many([{'note': 'bye'}, {'name': 'go'}])
# myset.insert([{'name': 'bye'}]) # 注意:pymongo 4.0.2不再使用insert()而使用insert_one()或insert_many()
运行后:
> show tables
courses
students
teachers
testset
> db.testset.find()
{ "_id" : ObjectId("6288a040b12f20513e1f0876"), "note" : "hello" }
查找
单个
result = myset.find_one({'note': 'hello'})
print(result)
# {'_id': ObjectId('6288a040b12f20513e1f0876'), 'note': 'hello'}
多个
result = myset.find() # 返回<pymongo.cursor.Cursor object at 0x000001AC24D49588>
print(result)
可以看到返回的是一个cursor,游标对象。这意味着它是可以去迭代遍历的,是一个迭代器。
for i in result:
print(i)
# 返回:
# {'_id': ObjectId('6288a040b12f20513e1f0876'), 'note': 'hello'}
# {'_id': ObjectId('6288a21b39c8ac16235cd5fc'), 'note': 'bye'}
# {'_id': ObjectId('6288a21b39c8ac16235cd5fd'), 'name': 'go'}
条件查找
result = myset.find({'$or': [{'note': 'bye'}, {'note': 'hello'}]})
for i in result:
print(i)
# {'_id': ObjectId('6288a040b12f20513e1f0876'), 'note': 'hello'}
# {'_id': ObjectId('6288a21b39c8ac16235cd5fc'), 'note': 'bye'}
# {'_id': ObjectId('6288a2777fa8a7cd0d258639'), 'note': 'bye'}
修改
# myset.update_one({'note': 'hello'}, {'note': 'halo'}) # 这样子会报错:
# ValueError: update only works with $ operators
myset.update_one({'note': 'hello'}, {'$set': {'note': 'halo'}}) # 修改第一个匹配成功的
myset.update_many({'name': 'go'}, {'$set': {'name': 'python'}}) # 修改所有匹配成功的
> db.testset.find()
{ "_id" : ObjectId("6288a040b12f20513e1f0876"), "note" : "halo" }
{ "_id" : ObjectId("6288a21b39c8ac16235cd5fd"), "name" : "python" }
{ "_id" : ObjectId("6288a2777fa8a7cd0d25863a"), "name" : "python" }
删除
myset.delete_one({'note': 'halo'})
> db.testset.find()
{ "_id" : ObjectId("6288a21b39c8ac16235cd5fc"), "note" : "bye" }
{ "_id" : ObjectId("6288a21b39c8ac16235cd5fd"), "name" : "python" }
{ "_id" : ObjectId("6288a2777fa8a7cd0d258639"), "note" : "bye" }
{ "_id" : ObjectId("6288a2777fa8a7cd0d25863a"), "name" : "python" }
myset.delete_many({})
> db.testset.find()
>