1.INSERT 插入
- 假设插入10条数据,第7条失败,则前6条插入成功,789不会成功。
- mongodb制作基本检查不超过16mb即可,插入非法数据很容易,注意只给信任的应用使用。
- 主流语言的驱动程序,对数据插入时候做校验。比如文档是否过大,文档是否包含非utf8的字符串,是否使用不可识别的类型。
1.1.db.collection.insertOne() 向集合中插入一条新文档。
db.ins.insertOne({name:'four doc',age:'4',tag:'four insert doc'})
返回结果
{
"acknowledged" : true,
"insertedId" : ObjectId("5c85f85806bbda89cc0dc44a")
}
1.2.db.collection.insertMany() 在集合中插入多个新文档。
操作
db.ins.insertMany([
{name:'five doc',age:'5',tag:'five insert doc'},
{name:'six doc',age:'7',tag:'six insert doc'},
{name:'seven doc',age:'8',tag:'seven insert doc'}
])
返回结果
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5c85f93806bbda89cc0dc44b"),
ObjectId("5c85f93806bbda89cc0dc44c"),
ObjectId("5c85f93806bbda89cc0dc44d")
]
}
1.3.db.collection.insert() 在集合中插入1条或多条文档(6.0抛弃,但还可用)
单条操作
db.ins.insert({name:'frist doc',age:'1',tag:'frist insert doc'})
返回结果:
WriteResult({ "nInserted" : 1 })
多条操作:
db.ins.insert([
{name:'sec doc',age:'2',tag:'sec insert doc'},
{name:'thr doc',age:'3',tag:'thr insert doc'}
])
返回结果:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
1.4.其他可以实现插入的操作
db.collection.update() 当upsert为true时//第三个参数 db.collection.updateOne() 当upsert为true时//第三个参数 db.collection.updateMany() 当upsert为true时//第三个参数 db.collection.findAndModify() 当upsert为true时** db.collection.findAndModify() 当upsert为true时** db.collection.findOneAndReplace() 当upsert为true时
2.UPDATE 更新
- $set 新增键和更新键(可以理解为mysql增加字段更新字段)
- $unset删除键(可以理解为mysql删除字段)
- $incr 键的值增减和减少,键的值只能是数字,键的类型只能是整型长整型或双精度浮点型不可是其他类型。
- $push 对数组的末尾添加元素
2.1 db.collection.update 更新记录
插入测试数据
db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5cbd706b35bc4d3801a312d1"),
ObjectId("5cbd706b35bc4d3801a312d2"),
....
....
]
}
2.2 db.collection.updateOne() 更新第一个符合条件的文档
更新前
db.inventory.find({item:"paper"})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0106"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
执行更新命令,会更新第一个符合条件的文档
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
})
结果,匹配到一条,修改一条
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
更新后
db.inventory.find({item:"paper"})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:38:32.820Z") }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0106"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
2.3 db.collection.updateMany() 更新多条文档,如果upsert为true且文档不存在则插入文档
更新前
db.inventory.find({qty:{$lt:50}})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc452"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0102"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0104"), "item" : "mousepad", "qty" : 25, "size" : { "h" : 19, "w" : 22.85, "uom" : "cm" }, "status" : "P" }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0108"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "status" : "A" }
执行更新命令
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)
结果,匹配到5条文档,修改5条文档
{ "acknowledged" : true, "matchedCount" : 5, "modifiedCount" : 5 }
更新后
db.inventory.find({qty:{$lt:50}})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "in" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:41:16.569Z") }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc452"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "in" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:41:16.570Z") }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0102"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "in" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:41:16.570Z") }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0104"), "item" : "mousepad", "qty" : 25, "size" : { "h" : 19, "w" : 22.85, "uom" : "in" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:41:16.570Z") }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0108"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 15.25, "uom" : "in" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:41:16.570Z") }
2.4 db.collection.replaceOne() 替换第一条符合条件的文档,并将新参数传递给replaceOne,不能替换ID字段。
更新前
db.inventory.find({item:"paper"})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-03-11T08:38:32.820Z") }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0106"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
执行更新命令
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
结果,匹配1条文档,修改1条文档
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
更新后
db.inventory.find({item:"paper"})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 40 } ] }
{ "_id" : ObjectId("5c861b4b274c7c6eff9c0106"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
将当前集合的文档转换为子文档(嵌套文档)
db.inventory.find()
{ "_id" : ObjectId("5fd07c9198ada1ce0d1e52a5"), "name" : "joe", "friends" : 32, "enemies" : 2 }
db.inventory.replaceOne(
{'name':'joe'},
{'name':'joe','relationships':{"friends" : 32,"enemies" : 2}}
)
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
db.inventory.find()
{ "_id" : ObjectId("5fd07c9198ada1ce0d1e52a5"), "name" : "joe", "relationships" : { "friends" : 32, "enemies" : 2 } }
bill-repli:PRIMARY>
2.5 db.collection.updateONE,updateMany,updateReplace 当upsert为true且记录不存在则插入新纪录
try {
db.inventory.updateOne(
{ "name" : "Pizza Rat's Pizzaria" },
{ $set: {"_id" : 4, "violations" : 7, "borough" : "Manhattan" } },
{ upsert: true }
);
} catch (e) {
print(e);
}
结果:因为没有匹配这条记录的条件。所以插入了一条新的记录。
{
"acknowledged" : true,
"matchedCount" : 0,
"modifiedCount" : 0,
"upsertedId" : 4
}
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "borough" : "Manhattan", "violations" : 7 }
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d" }
2.6 增加/更新字段set和删除字段unset
不加条件,则更新第一条文档记录
db.blog.update({},{$set:{'num':''}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d" }
增加条件name为c的文档,增加一个字段
db.blog.update({'name':'c'},{$set:{'num':'2'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c", "num" : "2" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d" }
不加条件,更新所有文档增加一个字段,更新所有会覆盖掉之前的值
db.blog.update({},{$set:{'num':''}},{multi:1})
WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 3 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d", "num" : "" }
添加条件为name:c,时删除一个字段
db.blog.update({'name':'c'},{$unset:{'num':''}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d", "num" : "" }
不加条件,删除第一条记录。
db.blog.update({},{$unset:{'num':''}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b", "num" : "" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d", "num" : "" }
不加条件,删除字段,更新所有已存在的文档。
db.blog.update({},{$unset:{'num':''}},{multi:1})
WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 2 })
db.blog.find()
{ "_id" : ObjectId("5fc5a6a3e78f91ca2839cb16"), "name" : "a" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb17"), "name" : "b" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb18"), "name" : "c" }
{ "_id" : ObjectId("5fc5a6c3e78f91ca2839cb19"), "name" : "d" }
可以使用javascript代码添加和更新键
db.blog.insert(post)
WriteResult({ "nInserted" : 1 })
db.blog.find()
{ "_id" : ObjectId("5fc4ba63bad2853e0468a3c8"), "title" : "My Blog Post", "connect" : "Here is my blog post.", "date" : ISODate("2020-11-30T09:24:41.117Z") }
添加一个评论字段
db.blog.find().pretty()
{
"_id" : ObjectId("5fc5a524e78f91ca2839cb15"),
"title" : "My Blog Post",
"connect" : "Here is my blog post.",
"date" : ISODate("2020-12-01T02:06:19.189Z")
}
post.comments = []
[ ]
db.blog.update({'title':'My Blog Post'},post)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.blog.find().pretty()
{
"_id" : ObjectId("5fc5a524e78f91ca2839cb15"),
"title" : "My Blog Post",
"connect" : "Here is my blog post.",
"date" : ISODate("2020-12-01T02:06:19.189Z"),
"comments" : [ ]
}
2.7 $incr自增自减
使用$inc插入一条记录
db.games.update({"game" : "pinball", "user" : "joe"},{$inc:{'score':50}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
因没有score这个键。在插入的时候自动创建这个键
db.games.find()
{ "_id" : ObjectId("5fd08a299ef0890ce971e161"), "game" : "pinball", "user" : "joe", "score" : 50 }
现在score增加10000
db.games.update({"game" : "pinball", "user" : "joe"},{$inc:{'score':10000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
则score变成10050
db.games.find()
{ "_id" : ObjectId("5fd08a299ef0890ce971e161"), "game" : "pinball", "user" : "joe", "score" : 10050 }
现在score减去5000
db.games.update({"game" : "pinball", "user" : "joe"},{$inc:{'score':-5000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
则score变为5050
db.games.find()
{ "_id" : ObjectId("5fd08a299ef0890ce971e161"), "game" : "pinball", "user" : "joe", "score" : 5050 }
2.8 数组的操作push,pull,pop,$(下标)
可以通过索引进行引用的列表,还可以作为数据集set来用
$push
对数组末尾添加一个元素,如果数组不存在创建一个新数组
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very good",
"email" : "123@163.com"
},
{
"content" : "very nice",
"email" : "abc@163.com"
},
123,
456,
789,
{
"content" : "very bad",
"eamil" : "456@163.com"
},
{
"content" : "very not nice",
"email" : "789@163.com"
}
]
}
不能用deleteOne来删除数组元素
db.game.deleteOne({'comments':123})
{ "acknowledged" : true, "deletedCount" : 0 }
使用$pull删除指定的数组元素。$pull是删除所有匹配条件的数组值
db.games.update({},{$pull:{'comments':123}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.update( {}, {$pull:{'comments':456}} )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.update( {}, {$pull:{'comments':789}} )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very good",
"email" : "123@163.com"
},
{
"content" : "very nice",
"email" : "abc@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
},
{
"content" : "very not nice",
"email" : "789@163.com"
}
]
}
使用$pop key:-1 来删除数组末尾的元素
db.games.update({},{$pop:{'comments':-1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
使用$pop key:1 来删除数组开头的元素
db.games.update({},{$pop:{'comments':1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very nice",
"email" : "abc@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
}
]
}
db.games.update( {"score" : 5050}, {$push:{'top10':{$each:[6,7,8,9,10,11,12,13,14,15,16,17,18]}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very nice",
"email" : "abc@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
}
],
"top10" : [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25
]
}
使用$push时,如要限制元素个数使用$push和$slice来搭配使用。保证不会超过设定好的长度,slice必须是负整数。
虽然push了26-33 8个元素。但是只保留最后5个元素。可以再清理的时候使用$sort。添加数据就必须需要清理。
db.games.update( {"score" : 5050}, {$push:{'top10':{$each:[26,27,28,29,30,31,32,33],$slice:-5}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very nice",
"email" : "abc@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
}
],
"top10" : [
29,
30,
31,
32,
33
]
}
只能改数组的部分内容
通过下标对email进行修改。由abc修改为def
db.games.update({'game':'pinball'},{$set:{'comments.0.email':'edf@163.com'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "very nice",
"email" : "edf@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
}
],
"top10" : [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12
]
}
通过下标来修改值。可以用$符号来替代下标。因为有些时候只有查询才能确定下标。
使用$可以不写下标地址。 $只更新第一个匹配的结果
db.games.update({'comments.content':'very nice'},{$set:{'comments.$.content':'double very nice'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.games.find().pretty()
{
"_id" : ObjectId("5fd08a299ef0890ce971e161"),
"game" : "pinball",
"user" : "joe",
"score" : 5050,
"comments" : [
{
"content" : "double very nice",
"email" : "edf@163.com"
},
{
"content" : "very bad",
"eamil" : "456@163.com"
}
],
"top10" : [
3,
4,
5,
6,
7,
8,
9,
10,
11,
12
]
}
2.9 upsert 记录存在则更新否则插入一条新数据
db.email.update({'name':'upsert'},
... {$set:{'name':'upsert',email:'upsert@163.com'}}
... )
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
db.email.find().pretty()
{
"_id" : ObjectId("5fd09fb79ef0890ce971e166"),
"name" : "abc",
"email" : "abc@163.com"
}
{
"_id" : ObjectId("5fd09fb79ef0890ce971e167"),
"name" : "def",
"email" : "def@163.com"
}
{
"_id" : ObjectId("5fd09fb79ef0890ce971e168"),
"name" : "ghi",
"email" : "ghi@163.com"
}
db.email.update({'name':'upsert'}, {$set:{'name':'upsert',email:'upsert@163.com'}},true )
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5fd718a37de2d14d3a30c553")
})
db.email.find().pretty()
{
"_id" : ObjectId("5fd09fb79ef0890ce971e166"),
"name" : "abc",
"email" : "abc@163.com"
}
{
"_id" : ObjectId("5fd09fb79ef0890ce971e167"),
"name" : "def",
"email" : "def@163.com"
}
{
"_id" : ObjectId("5fd09fb79ef0890ce971e168"),
"name" : "ghi",
"email" : "ghi@163.com"
}
{
"_id" : ObjectId("5fd718a37de2d14d3a30c553"),
"name" : "upsert",
"email" : "upsert@163.com"
}
3.DELETE 删除
3.1.db.collection.deleteOne() 删除符合条件的第一条文档
执行删除操作
db.inventory.deleteOne( { status: "D" } ) 删除status为D的文档记录
返回结果:
{ "acknowledged" : true, "deletedCount" : 1 } 提示删除了1条记录
3.2 db.collection.deleteMany() 删除所有符合条件的文档
执行删除操作
db.inventory.deleteMany({ status : "A" }) 删除status为A的文档记录
返回结果:
{ "acknowledged" : true, "deletedCount" : 7 } 提示删除7条记录
3.3 也可以做删除操作的命令
db.collection.findOneAndDelete() 提供排序选项。该选项允许删除按指定顺序排序的第一个文档。
db.collection.findAndModify() 提供排序选项。该选项允许删除按指定顺序排序的第一个文档。
例:
db.ins.findAndModify({query:{'age':'9'},remove:true})
4.FIND 查询
- 对于要查询的文档的值必须是常量
4.1 查询所有记录
类似于MySQL中的 select * from table
db.inventory.find()/db.inventory.find({}) 两条命令相等
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44f"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
4.2 条件查询
类似于MYSQL中 SELECT * FROM inventory WHERE status = "D"
db.inventory.find( { status: "D" } ) 找到status等于D的文档。
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc451"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "status" : "D" }
4.3 IN查询
类似于MYSQL中SELECT * FROM inventory WHERE status in ("A", "D") 虽然可以使用or来做操作。但是官方更推荐使用in来查询。
db.inventory.find({ status: { $in: [ "A", "D" ]}}) 搜索status等于A或D的文档。
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44f"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc450"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "D" }
4.4 AND查询
类似于MYSQL中 select * from inventory where status="A" and qty<30
and操作。找到status等于A且qty小于30的文档。
db.inventory.find({status:"A",qty:{$lt:30}})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
4.5 OR查询
类似于MYSQL中SELECT * FROM inventory WHERE status = "A" OR qty < 30
查询status等于A 或 qty> 30的记录
db.inventory.find({$or:[{status:"A"},{qty:{$lt:30}}]})
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44e"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5c85fcd906bbda89cc0dc44f"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "status" : "A" }
4.6 排序/美化/限制输出结果/跳过结果输出
Sort排序/Pretty美化
db.inventory.find().sort({name:1}).pretty() 对name字段进行排序,并且美化输出结果。
db.ins.find().sort({name:1}).pretty()
{
"_id" : ObjectId("5c85f93806bbda89cc0dc44b"),
"name" : "five doc",
"age" : "5",
"tag" : "five insert doc"
}
{
"_id" : ObjectId("5c85f85806bbda89cc0dc44a"),
"name" : "four doc",
"age" : "4",
"tag" : "four insert doc"
}
email有5个集合
db.email.count()
Limit限制返回结果 只返回2个结果
db.email.find().limit(2)
{ "_id" : ObjectId("5fd09fb79ef0890ce971e166"), "name" : "abc", "email" : "abc@163.com" }
{ "_id" : ObjectId("5fd09fb79ef0890ce971e167"), "name" : "def", "email" : "def@163.com" }
Skip跳过文档返回剩余文档 跳过前两个结果,返回余下的结果。
db.email.find().skip(2)
{ "_id" : ObjectId("5fd09fb79ef0890ce971e168"), "name" : "ghi", "email" : "ghi@163.com" }
{ "_id" : ObjectId("5fd718a37de2d14d3a30c553"), "name" : "up", "email": "upsert@163.com" }
{ "_id" : ObjectId("5fd71a2a2f1e32c5f863d32b"), "name" : "abc", "email" : "abc@164.com" }
4.7 查询数组文档(测试未通过在研究,跳过这一条)
查询数组文档
db.ins.insert({"name" : "11.sz", "age" : "11", "tags":["java","kpop","china"]})
db.ins.insert({name:'12',age:12,tags:[{'code':'java','music':'kpop'}]})
查询
db.ins.find()
[ { _id: ObjectId("64dc11fea08ca24713ab4c56"), name: '11.sz', age: '11', tags: [ 'java', 'kpop', 'china' ]
},
{
_id: ObjectId("64dc11ffa08ca24713ab4c57"),
name: '12',
age: 12,
tags: [ { code: 'java', music: 'kpop' } ]
}
]
精确匹配数组文档,如果有一个字段是只有java才返回结果
db.ins.find({tags:["java"]})
精确匹配数组文档,有java,kpop,china才会返回结果。
db.ins.find({tags:["java","kpop","china"]})
db.ins.find({tags:"java"}) 模糊匹配,只要tags中带了java的就展示
{
_id: ObjectId("64dc11fea08ca24713ab4c56"),
name: '11.sz',
age: '11',
tags: [ 'java', 'kpop', 'china' ]
}
]
模糊匹配,只要tags中带了bike的就展示
db.ins.find({tags:"kpop"}) 模糊匹配,只要tags中带了bike的就展示
4.8 模糊查询
类似MySQL中的 select * from users where name like '%a%'
db.users.find({name:/.*a.*/}) 模糊匹配查询,带a字母的,无论a在前后
db.users.find({name:/^a.*/}) 模糊匹配查询,name以a开头的结果查询
db.users.find({name:/.*a$/}) 模糊匹配查询,name以a结尾的结果查询
4.9 嵌套文档查询/投影(只返回特定字段)
文档嵌套查询
(用户评论,商品订单,买了一个东西,商品的名称价格数量)(例子)
{ "_id" : ObjectId("5b58b9544983f690c7ab9687"), "name" : "baby3", "age" : 18, "address" : { "country" : "china", "city" : "hangzhou", "district" : "xihu", "dd" : "zhongguancunroad 10" } }
{ "_id" : ObjectId("5b58b9784983f690c7ab9688"), "name" : "xiaowang", "age" : 19, "address" : { "country" : "china", "city" : "shanghai", "district" : "pudong", "dd" : "sjtu park 10" } }
查询时应该包含外围的字段和内部的字段,可以不按顺序来查询。也可以严格按照顺序来查询。
db.users.find({"address.country":'china'}) country是address文档中的字段,注意用.来引用
db.users.find({"address.city":'hangzhou'})
db.users.find({age:18,"address.city":'hangzhou'})
db.users.find({age:{$lt:18},"address.city":'hangzhou'}) 可以使用条件来限制比如年龄小于18岁的
db.orders.find({'item.0.count':{$lt:2}}) 第0个元素满足,按照第一个元素范围是大于2的。
db.orders.find({"item.count":{$gt:0,$lte:100}}) 多条件and查询
投影(映射)返回特定的字段
db.users.find({age:18},{name:1,age:1}) 查询年龄是18岁的。但只返回name字段和age字段
db.users.find({age:{$gt:29}},{name:1,age:1}) 查询年龄大于29的。但是只返回name和age字段
db.users.find({age:{$gt:29}},{name:0}) 查询年龄大于29的。不返回name字段,剩下都返回
4.10 去重/聚合
distinct去重
db.users.distinct("name") 去掉重复的名字,显示不重复的名字
db.orders.distinct("items.count") 去掉重复的计数,显示不重复的计数
db.users.distinct("name ",{age:18}) 查询年龄等于18的,并对name字段进行去重
db.orders.distinct("item.count ",{age:18}) 查询年龄18岁的。并对items.count计数字段去重
db.users.distinct("city")
db.users.distinct("address.city")
等价写法
db.runCommand({distinct:"users",key:"name"})
为了性能,尽量使用索引,支持优先查询节点。
group by聚合统计分析
有三种,聚合函数(早期功能),聚合管道,mapreduce(应对大数据分析)。
简单的使用group方法。3.4过期,建议使用新的聚合,db.collections.aggregate()+$group或者db.collections.mapreduce
分组统计不同年龄段的用户
db.users.group(
{
key:{age:1},
cond:{age:{$gt:16}},
reduce:function(curr,result){
result.total +=1;
},
initial:{total:0}
}
)
分组统计不同用户的订单总额
db.orders.grop(
{
key:{name:1},
cond:{},
reduce:function(curr.result){
result.total += curr.price;
},
initial:{total:0}
}
)
分组统计不同用下的订单数
db.orders.group(
{
key:{name:1},
cond:{},
reduce:function(curr,result){
result.total +=1; },
initial:{total:0}
}
)
分组统计不同用户消费金额
db.orders.group(
{
key:{name:1},
cond:{},
reduce:function(curr,result){
result.total =curr.price
},
initial:{total:0}
}
)
4.11 null值的查询
a集合包含一个null值
db.a.find()
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab90"), "y" : null }
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab91"), "y" : 1 }
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab92"), "y" : 2 }
通过条件查询可以查询到这个null值
db.a.find({'y':null})
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab90"), "y" : null }
对于不存在的z查询的时候,会返回所有的值
db.a.find({'z':null})
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab90"), "y" : null }
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab91"), "y" : 1 }
{ "_id" : ObjectId("5fd9b25c1d2a682a33b3ab92"), "y" : 2 }
检查z是否为null值,还要通过exists判断键是否存在。可以避免上边的问题。
db.a.find({'z':{$in:[null],$exists:true}})
4.12 FIND补充
| Find操作符 | 作用 | |
|---|---|---|
| 查询操作符 | ||
| 比较查询运算符 | ||
| $eq | 匹配等于指定值的值。 | |
| $gt | 匹配大于指定值的值。 | |
| $gte | 匹配大于或等于指定值的值 | |
| $in | 匹配数组中指定的任何值。 | |
| $lt | 匹配小于指定值的值。 | |
| $lte | 匹配小于或等于指定值的值。 | |
| $ne | 匹配所有不等于指定值的值。 | |
| $nin | 不匹配数组中指定的任何值。 | |
| 逻辑查询运算符 | ||
| $and | 使用逻辑连接查询子句AND将返回与两个子句的条件匹配的所有文档。 | |
| $not | 反转查询表达式的效果并返回与查询表达式不匹配的文档。 | |
| $nor | 使用逻辑连接查询子句NOR将返回所有无法匹配两个子句的文档。 | |
| $or | 使用逻辑连接查询子句OR将返回与任一子句的条件匹配的所有文档。 | |
| 元素查询运算符 | ||
| $exists | 匹配具有指定字段的文档。 | |
| $type | 如果字段是指定类型,则选择文档。 | |
| 求值查询运算符 | ||
| $expr | 允许在查询语言中使用聚合表达式。 | |
| $jsonSchema | 根据给定的JSON模式验证文档。 | |
| $mod | 对字段的值执行模运算,并选择具有指定结果的文档。 | |
| $regex | 选择值与指定正则表达式匹配的文档。 | |
| $text | 执行文本搜索 | 。 |
| $where | 匹配满足JavaScript表达式的文档。 | |
| 地理空间查询运算符 | ||
| $geoIntersects | 选择与GeoJSON几何体相交的几何。该2dsphere索引支持 | |
| $geoWithin | 选择边界GeoJSON几何体内的几何。该2dsphere和2D索引支持。 | |
| $near | 返回点附近的地理空间对象。需要地理空间索引。 | |
| $nearSphere | 返回球体上某点附近的地理空间对象。需要地理空间索引。 | |
| 数组查询运算符 | ||
| $all | 匹配包含查询中指定的所有元素的数组 | |
| $elemMatch | 如果数组字段中的元素与所有指定$elemMatch条件匹配,则选择文档。 | |
| $size | 如果数组字段是指定大小,则选择文档。 | |
| 按位查询运算符 | ||
| $bitsAllClear | 匹配数值或二进制值,其中一组位位置都具有值0。 | |
| $bitsAllSet | 匹配数值或二进制值,其中一组位位置都具有值1。 | |
| $bitsAnyClear | 匹配数值或二进制值,其中来自一组位位置的任何位的值都为0。 | |
| $bitsAnySet | 匹配数值或二进制值,其中来自一组位位置的任何位的值都为1。 | |
| 投影查询运算符 | ||
| $ | 投影数组中与查询条件匹配的第一个元素。 | |
| $elemMatch | 投影数组中与指定$elemMatch条件匹配的第一个元素。 | |
| $meta | 投影在$text操作期间分配的文档分数。 | |
| $slice | 限制从数组投射的元素数量。支持跳过和限制切片。 |