『NoSQL - MongoDB』CRUD
前言
本文从讲解了 MongoDB 的数据导入导出,以及 CRUD 操作。
数据下载:
JSON示例数据:(美国马萨诸塞州邮政代码->点击下载)。
{
"_id" : "01001", #序号
"city" : "AGAWAM", #城市
"loc" : [ #坐标
-72.622739,
42.070206
],
"pop" : 15338, #标记
"state" : "MA" #州缩写
}
其他 JSON 数据下载:http://jsonstudio.com/resources/
MongoDB - 导入数据:
简介:
mongoimport工具从由其他第三方导出工具创建或可能的[扩展JSON],CSV或TSV导出导入内容`mongoexport。
mongoimport是以系统命令行运行,而不是MongoShell。
操作:
json 导入:
示例代码:
mongoimport --db jsonar --collection zips --file /Users/Desktop/zips.json
- –db:数据库名称
- –collection:集合名称
- –file:文件路径
csv导入:
示例代码:
mongoimport --db users --collection contacts --type csv --headerline --file /opt/backups/contacts.csv
- –type: 文件类型
注意事项:
mongoimport
支持UTF-8编码的数据文件。使用其他编码会产生错误。
Reference:https://docs.mongodb.com/manual/reference/program/mongoimport/index.html
MongoDB - 导出数据:
简介:
mongoexport 是一个实用程序,可以生成一个JSON或CSV导出存储在MongoDB实例中的数据。
mongoimport是以系统命令行运行,而不是MongoShell。
操作:
json导出:
mongoexport --db jsonar --collection zips --out ~/Desktop/zips.json
csv导出:
mongoexport --db jsonar --collection zips --out ~/Desktop/zips.csv
–out 参数指定了导出的文件类型以及文件路径,更多导出方式请参考官方文档。
Reference:https://docs.mongodb.com/manual/reference/program/mongoexport/index.html
MongoDB - 插入文档:
在向 MongoDB 数据库中执行插入操作的时候,如果集合(collection)不存在,插入操作会自动创建一个集合**(当然,MongoDB 也提供了db.createCollection("emp");
方法来创建集合)**,存储于集合中的每一个文档都需要一个唯一的_id
字段作为 primary_key。如果一个插入文档操作遗漏了_id
字段,MongoDB驱动会自动为_id
字段生成一个 [ObjectId],这种情况同样适用于带有参数的 [upsert: true]的 update 操作。
MongoDB主要提供了以下三个方法向集合插入文档:
- db.collection.insertOne()
- db.collection.insertMany()
- db.collection.insert()
insertOne:
db.collection.insertOne()
将单个文档插入到集合中。
示例代码:
db.inventory.insertOne(
... { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
... )
运行结果:
{
"acknowledged" : true,
"insertedId" : ObjectId("59eee499cbb5fc46080e6d87")
}
insertOne() 返回一个结果文档,该结果文档中列举了插入文档的_id
字段值为ObjectId("59eee499cbb5fc46080e6d87")
。
insertMany:
db.collection.insertMany()
可以将多个文档插入到集合中。
示例代码:
db.inventory.insertMany([
... { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
... { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
... { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
... ])
运行结果:
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("59eeeb7dcbb5fc46080e6d89"),
ObjectId("59eeeb7dcbb5fc46080e6d8a"),
ObjectId("59eeeb7dcbb5fc46080e6d8b")
]
}
insertMany() 返回包含新插入的文档_id字段值的文档。
insert:
db.collection.insert()
将单个文档或多个文档插入到集合中。
插入单个文档:
示例代码:
db.products.insert( { item: "card", qty: 15 } )
运行结果:
WriteResult({ "nInserted" : 1 })
插入多个文档:
示例代码:
db.products.insert(
[
{ _id: 11, item: "pencil", qty: 50, type: "no.2" },
{ item: "pen", qty: 20 },
{ item: "eraser", qty: 25 }
]
)
运行结果:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 3,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
MongoDB - 读取文档:
MongoDB 提供了 db.collection.find()
方法从集合中读取文档。此方法返回一个游标,要访问文档,需要迭代游标。但是,在MongoShell中,如果返回的游标未使用var关键字分配给变量,那么光标自动迭代最多20次,打印到结果中的前20个文档。(可以使用 DBQuery.shellBatchSize
来改变迭代次数的默认值 20
。)
要查询集合中的所有文档,需要将空文档作为查询过滤器参数传递给find方法。
基础查询:
查询 zips 集合中的全部数据,示例代码:
db.zips.find({});
运行结果:
{ "_id" : "01001", "city" : "AGAWAM", "loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" }
{ "_id" : "01002", "city" : "CUSHMAN", "loc" : [ -72.51565, 42.377017 ], "pop" : 36963, "state" : "MA" }
{ "_id" : "01005", "city" : "BARRE", "loc" : [ -72.108354, 42.409698 ], "pop" : 4546, "state" : "MA" }
{ "_id" : "01007", "city" : "BELCHERTOWN", "loc" : [ -72.410953, 42.275103 ], "pop" : 10579, "state" : "MA" }
{ "_id" : "01008", "city" : "BLANDFORD", "loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" }
如果觉得返回结果太乱,可以使用.pretty()
来格式化显示。
查询时也可以指定不需要显示的字段,示例代码:
db.zips.find({},{"loc":0})
运行结果:
/* 1 */
{
"_id" : "01001",
"city" : "AGAWAM",
"pop" : 15338,
"state" : "MA"
}
/* 2 */
{
"_id" : "01002",
"city" : "CUSHMAN",
"pop" : 36963,
"state" : "MA"
}
/* 3 */
{
"_id" : "01005",
"city" : "BARRE",
"pop" : 4546,
"state" : "MA"
}
对于设置的显示字段严格来讲就称为数据的投影操作,如果不需要显示的字段设置“0”,而需要显示的字段设置“1”。
查询时也可以指定相等条件,语法db.集合名称.find({查询条件} [,{设置显示的字段}]
。
示例代码:
db.inventory.find( { city: "SPRINGFIELD" } )
运行结果:
/* 1 */
{
"_id" : "01103",
"city" : "SPRINGFIELD",
"loc" : [
-72.588735,
42.1029
],
"pop" : 2323,
"state" : "MA"
}
/* 2 */
{
"_id" : "01104",
"city" : "SPRINGFIELD",
"loc" : [
-72.577769,
42.128848
],
"pop" : 22115,
"state" : "MA"
}
/* 3 */
{
"_id" : "01105",
"city" : "SPRINGFIELD",
"loc" : [
-72.578312,
42.099931
],
"pop" : 14970,
"state" : "MA"
}
关系运算:
在MongoDB里面支持的关系查询操作:大于($gt)、小于($lt)、大于等于($gte)、小于等于($lte)、不等于($ne)、等于(key:value、$eq)。
查询pop大于20000的数据:
$gt:
db.zips.find({pop:{$gt:20000}})
$lt:
查询pop小于1000的数据 :
db.zips.find({pop:{$lt:1000}})
$gte:
查询pop 大于等于90000的数据:
db.zips.find({pop:{$gte:90000}})
$lte:
查询 pop 小于等于10的数据:
db.zips.find({pop:{$lte:10}})
$ne:
查询 pop 不等于100的数据:
db.zips.find({pop:{$ne:100}})
$eq:
查询 pop 等于100的数据:
db.zips.find({pop:{$eq:100}})
逻辑运算:
逻辑运算主要就是三种类型:与($and)、或($or)、非($not、$nor)。
$and:
查询 pop为等于10000和city 存在的数据(显式$and查询):
db.zips.find({$and:[{pop:{$ne:10000}},{city:{$exists:true}}]})
查询pop值再10000 - 20000之间的数据(隐式$and查询):
db.zips.find({pop:{$gte:10000,$lte:20000}})
$or:
查询city 为SPRINGFIELD或者pop 大于10000的数据:
db.zips.find({$or:[{city:"SPRINGFIELD"},{pop:{$gte:10000}}]})
$nor:
查询city 不为SPRINGFIELD或者 pop 小于10000的数据(进行或的取反操作):
db.zips.find({$nor:[{city:"SPRINGFIELD"},{pop:{$gte:10000}}]})
求模运算:
$mod:
求模运算使用“$mod”来完成,语法“{$mod : [数字,余数]}”。
db.zips.find({pop:{$mod:[100,10]}})
范围查询:
“$in”(在范围之中)、“$nin”(不在范围之中)
$in:
查询 city 为AGAWAM、CUSHMAN、SPRINGFIELD三个值的数据:
db.zips.find({city:{$in:["AGAWAM","CUSHMAN","SPRINGFIELD"]}})
$nin:
查询 city 中不含AGAWAM、CUSHMAN、SPRINGFIELD三个值的数据:
db.zips.find({city:{$nin:["AGAWAM","CUSHMAN","SPRINGFIELD"]}})
数组查询:
MongoDB中,需要针对于数组数据查询操作,可以使用几个运算符:$all、$size、$slice、$elemMatch。
$all:
查询loc 有42.070206的数据:
db.zips.find({loc:{$all:[42.070206]}})
虽然“$all”计算可以用于数组上,但是也可以用于一个数据的匹配上。
查询loc 有-72.108354和42.409698的数据:
db.zips.find({loc:{$all:[-72.108354,42.409698]}})
$size:
查询 loc中字段数量为2的数据:
db.zips.find({loc:{$size:2}})
$slice:
查询 loc中city为SPRINGFIELD并且字段数量为2的数据:
db.zips.find({city:"SPRINGFIELD"},{loc:{$slice:1}})
查询 loc中city为SPRINGFIELD的数据数据跳过第一条数据返回两条数据:
db.zips.find({city:"SPRINGFIELD"},{loc:{$slice:[1,2]}})
下标查询:
查询 loc中数组的第二个字段,值为42.070206的数据:
db.zips.find({"loc.1":42.070206})
既然在集合里面现在保存的是数组信息,那么数组就可以利用索引操作,使用“key.index”的方式来定义索引。
条件过滤:
$where:
查询 pop 值小于10的数据:
db.zips.find({$where:"this.pop < 10"});
查询 pop 值小于10的数据和id大于10000的值:
db.zips.find({"$and":[{"$where":"this.pop < 10"},{"$where":"this._id > 10000"}]})
正则匹配:
在 MongoDB 中,如果想模糊查询,那就要使用正则表达式来匹配,而且正则表达式使用的是语言Perl兼容的正则表达式的形式。如果要想实现正则使用,则按照如下的定义格式:
·基础语法:{key : 正则标记};
·完整语法:{key : {“$regex” : 正则标记 , “$options” : 选项}}。
指令 | 释义 | 语法 |
---|---|---|
i | 忽略字母大小写 | |
m | 在每行的开始或结尾匹配具有多行值的字符串(多行查找) | |
x | 空白字符串除了被转义的或在字符类中意外的完全被忽略 | 需要$ regex与$ options语法 |
s | 匹配所有的字符(圆点、“.”),包括换行内容。 | 需要$ regex与$ options语法 |
查询 state中以 K 开头的数据(^):
db.zips.find({state:/^K/})
查询 state中包含 k 的数据(不区分大小写):
db.zips.find({state:/k/i})
db.zips.find({state:{$regex:/K/i}})
两种写法均可实现。
数据排序:
MongoDB中数据的排序操作使用“sort()”函数,在进行排序的时候可以有两个顺序:升序(1)、降序(-1)。
查询 pop 数据进行升序排序:
db.zips.find({}).sort({pop:1})
查询 id 数据进行降序排序:
db.zips.find({}).sort({_id:-1})
数据分页:
- skip(n):表示跨过多少数据行;
- limit(n):取出的数据行的个数限制。
查询从0开始每页显示10条数据根据 id升序排序:
db.zips.find({}).skip(0).limit(10).sort({"_id":1})
db.zips.find({}).skip(10).limit(10).sort({"_id":1})
其他查询:
$exists:
查询 pop 的值存在且不含1000-5000之间的数据:
db.zips.find( { pop: { $exists: true, $nin: [ 1000, 5000 ] } } )
MongoDB - 更新文档:
在MongoDB中,对于数据的更新操作提供了两类函数:save()、update()。
方法名称 | 使用介绍 |
---|---|
db.collection.updateOne() | 即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新一个文档。 |
db.collection.updateMany() | 更新所有通过过滤条件匹配到的文档 |
db.collection.replaceOne() | 即使可能有多个文档通过过滤条件匹配到,但是也最多也只替换一个文档。 |
db.collection.update() | 即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新或者替换一个文档。 |
默认情况下db.collection.update()
只更新一个文档。要更新多个文档,请使用 multi 选项。
修改器:
$set:
$set用来指定一个键的值
$unset:
$unset用来将键完全删除
$inc:
用于,增加和减少:
1、键不存在时创建一个键
2、增加已有键的值
对于分析数据、因果关系、投票或者其他变化数值的地方,使用这个非常方便。
save:
save() 方法通过传入的文档来替换已有文档.
示例代码:
db.zips.save({
"_id" : "01001",
"city" : "AGAWAM",
"loc" : [
-72.622739,
42.070206
],
"pop" : 15338,
"state" : "ZHN"
})
运行结果:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
update:
语法:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
upsert:布尔值可选。如果设置为true,则在没有文档与查询条件匹配时创建新文档。默认值为false,在找不到匹配项时不插入新文档。
示例代码:
db.zips.update({ _id: 01001},{"city":"ShenZhen","state":"ZHN"},{upsert: true})
运行结果:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
updateOne:
语法:
db.collection.updateOne(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
示例代码:
db.zips.updateOne({"_id":"01002"},{$set:{state:"CHN"}})
运行结果:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
updateMany:
语法:
db.collection.updateMany(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
参数说明:
参数 | 类型 | 详解 |
---|---|---|
filter | document | 更新的选择条件,与find()方法中的查询选择器使用方式相同,可以 指定一个空文档{}来更新集合中的所有文档。 |
update | document | 使用更新操作符,如$ set,$ unset或$ rename。 使用update()模式的更改参数的值:value引发错误。 |
upsert | boolean | 可选参数。当为true时,updateMany() 如果没有文档与过滤器匹配,则创建新文档。 更新与过滤器匹配的文档。 为了避免多个提前插入,请确保过滤器字段被唯一索引。 默认为false。 |
writeConcern | document | 可选参数。描述MongoDB对独立mongod或复制集合或分片集群的写操作所请求的确认级别,省略使用默认的写入关注。 |
collation | document | 可选参数。 指定要用于操作的排序规则。 排序规则允许用户指定用于字符串比较的特定于语言的规则,例如字母和重音符号的规则。 |
示例代码:
db.zips.updateMany({ "state" : "CHN" },{ $set: { pop: "1000"}},{upsert:true});
运行结果:
{"acknowledged" : true, "matchedCount" : 1.0, "modifiedCount" : 0.0}
replaceOne:
语法:
db.collection.replaceOne(
<filter>,
<replacement>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
示例代码:
db.zips.replaceOne({ "state" : "CHN" },{ "pop" : 0, "state" : "CHINA"});
运行结果:
{"acknowledged" : true,"matchedCount" : 1.0,"modifiedCount" : 1.0}
MongoDB - 删除文档:
MongoDB提供以下方法来删除集合的文档:
方法 | 说明 |
---|---|
db.collection.deleteOne() | 最多删除与指定过滤器匹配的单个文档,即使多个文档可能与指定的过滤器匹配。 |
db.collection.deleteMany() | 删除与指定过滤器匹配的所有文档。 |
db.collection.remove() | 删除单个文档或与指定过滤器匹配的所有文档。 |
deleteOne:
语法:
db.collection.deleteOne(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)
选项说明:
- filter:类型为 document;使用查询运算符指定删除条件,指定一个空文档
{}
删除集合中返回的第一个文档。 - writeConcern:类型为document;可选参数;描述MongoDB对独立mongod或复制集合或分片集群的写操作所请求的确认级别,省略使用默认的写入关注。
- collation:类型为document;可选参数;指定要用于操作的排序规则。 排序规则允许用户指定用于字符串比较的特定于语言的规则,例如字母和重音符号的规则。
示例代码:
db.zips.deleteOne({state:"CHINA"},{})
运行结果:
{"acknowledged" : true,"deletedCount" : 1.0}
deleteMany:
语法:
db.collection.deleteMany(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)
删除所有符合 state:"MA"
的数据:
db.zips.deleteMany({state:"MA"},{})
运行结果:
{"acknowledged" : true,"deletedCount" : 472.0}
删除所有符合state中以R开头的数据(不区分大小写):
db.zips.deleteMany({state:/^R/i},{})
运行结果:
{"acknowledged" : true,"deletedCount" : 70.0}
remove:
romeve函数有两个选项:
- 删除条件:满足条件的数据被删除;
- 是否只删除一个数据,如果设置为true或者是1表示只删除一个。
语法:
db.collection.remove(
<query>,
<justOne>
)
选项说明:
- query:类型为document;使用查询运算符指定删除条件,需要清空集合,可以指定为
{}
。 - justOne:类型为document;可选参数;要将删除限制为只有一个文档,请设置为
true
。省略使用默认值false
并删除符合删除条件的所有文档。
删除 pop 小于2000的数据:
db.zips.remove({pop:{$lt:2000}})
运行结果:
Removed 12436 record(s) in 180ms
删除 city 为MASON的数据,只删除一个:
db.zips.remove({city:"MASON"},{justOne:true})
运行结果:
Removed 1 record(s) in 1ms
删除_id 中带有9的数据:
db.zips.remove({_id:/9/})
运行结果:
Removed 5255 record(s) in 91ms
清空集合zips
中的所有内容:
db.zips.remove({})
运行结果:
Removed 11235 record(s) in 136ms
删除zips 集合:
db.zips.drop()
运行结果:
true
参考资料:
查询运算符:https://docs.mongodb.com/manual/reference/operator/query/
MongoDB-CRUD:https://docs.mongodb.com/manual/crud/
MongoDB-writeConcern:https://docs.mongodb.com/manual/reference/write-concern/