基于mongodb v4.2
插入数据
插入一条数据
db.collection.insertOne() 插入一个文档到集合中
try {
db.products.insertOne( { item: "card", qty: 15 } );
} catch (e) {
print (e);
};
// 返回值:
{
"acknowledged" : true,
"insertedId" : ObjectId("56fc40f9d735c28df206d078")
}
插入多条数据
db.collection.insertMany() 同时插入多条数据到集合中
try {
db.products.insertMany( [
{ item: "card", qty: 15 },
{ item: "envelope", qty: 20 },
{ item: "stamps" , qty: 30 }
] );
} catch (e) {
print (e);
}
// 返回值:
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("562a94d381cb9f1cd6eb0e1a"),
ObjectId("562a94d381cb9f1cd6eb0e1b"),
ObjectId("562a94d381cb9f1cd6eb0e1c")
]
}
insert 特性: 如果当前集合不存在,会自动创建一个集合。
_id 属性: mongodb里面,如果你不提供_id,mongodb会默认在插入文档的时候为每一个文档创建一个唯一的_id,作为主键
查找数据
mongodb可以使用find方法查找数据
普通查询
每个文档插入到集合中如果不提供一个_id字段,则mongodb会自动生成一个,并且在查询语句中默认返回,这里省略没有显示该字段
// 示例数据
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ 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" }
]);
// 查找 size 等于 { h: 14, w: 21, uom: "cm" } 的数据
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
// or 查找 qty 等于 25 的数据
db.inventory.find({ qty: 25 })
// or 使用嵌套查询 size 的 uom 等于 in 的数据
db.inventory.find( { "size.uom": "in" } )
// $lt 小于
db.inventory.find( { "size.h": { $lt: 15 } } )
// 复合条件查询,查询 size.h 小于 15, 并且 size.uom 等于 in,并且 status 等于 D 的数据
db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )
查询数组
// 示例数据
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
{ item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
{ item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
{ item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
{ item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);
// 查询 tags 等于 ["red", "blank"] 的数据
db.inventory.find( { tags: ["red", "blank"] } )
// 或者你想查询tags包含 red blank,不管它的顺序,或者是否还有其他元素,你可以使用 `$all`
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
// 查询tags 里面包含 red的数据
db.inventory.find( { tags: "red" } )
// 查询dim_cm里面最少有一个值大于 25
db.inventory.find( { dim_cm: { $gt: 25 } } )
/*
** 查询dim_cm里面:
** 1. 有一个元素同时满足大于15并且小于20
** 2. 有两个分别满足小于15以及大于20
*/
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
// 所以结果是返回这四条:
{ "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "item" : "postcard", "qty" : 45, "tags" : [ "blue" ], "dim_cm" : [ 10, 15.25 ] }
// 查询dim_cm里面至少有一个元素同时满足大于22并且小于30的数据
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
// 查询dim_cm第二个元素大于25的数据
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
// 查询dim_cm的tags数组长度为3的数据
db.inventory.find( { "tags": { $size: 3 } } )
// 示例数据
db.inventory.insertMany( [
{ item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
{ item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
{ item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
{ item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
// 查询instock数组里面有一个元素为{ warehouse: "A", qty: 5 }的数据,必须warehouse等于A并且qty等于5,包括顺序也必须一致
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
// 查询instock数组里面至少有一个元素的qty字段值小于等于20的数组
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
// 结果为:
{ "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "item" : "notebook", "instock" : [ { "warehouse" : "C", "qty" : 5 } ] }
{ "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
{ "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
// 查询instock数组的第一个元素的qty字段小于等于20的数据
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
// 查询instock数组里至少有一个元素同时满足qty等于5并且warehouse等于A的数组
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
// 查询instock数组里至少有一个元素的qty同时满足大于10并且小于等于20
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
// 查询instock数组里至少有一个元素满足大于10或者小于等于20
db.inventory.find( { "instock.qty": { $gt: 10, $lte: 20 } } )
// 结果为:
{ "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
{ "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
// 查询instock里任意一个元素的qty等于5并且任意一个元素的warehouse等于A的数据
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
// 结果为:
{ "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
控制查询语句输出结果
默认情况下,查询语句会返回文档的所有字段,我们可以通过第二个参数来自定义返回文档里的哪些字段
关于第一个参数,我们这里就不详细说明了,可参考上面
// 示例数据
db.inventory.insertMany( [
{ item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
{ item: "notebook", status: "A", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
{ item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
{ item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
// 返回所有文档的status为的A的数据的所有字段
db.inventory.find( { status: "A" } )
// 只返回文档的item, status字段以及_id(默认显示),1代表显示,0则是不显示
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
// 如果想要_id也不返回,可以这样:
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
// 也可以单独给某些不想显示的字段设为0,其余的正常显示
db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
// 还可以控制嵌套对象的字段,下面语句只显示_id, item, status, 以及size的uom字段
db.inventory.find(
{ status: "A" },
{ item: 1, status: 1, "size.uom": 1 }
)
// 也可以只设置不显示某个嵌套字段,下面语句不显示size的uom属性,其余正常显示
db.inventory.find(
{ status: "A" },
{ "size.uom": 0 }
)
// 控制数组中的元素某些字段是否显示
db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )
// 结果为:
{ "_id" : ObjectId("5e639b35940e1ec922af0d51"), "item" : "journal", "status" : "A", "instock" : [ { "qty" : 5 } ] }
{ "_id" : ObjectId("5e639b35940e1ec922af0d52"), "item" : "notebook", "status" : "A", "instock" : [ { "qty" : 5 } ] }
{ "_id" : ObjectId("5e639b35940e1ec922af0d55"), "item" : "postcard", "status" : "A", "instock" : [ { "qty" : 15 }, { "qty" : 35 } ] }
// 对于instock,只返回数组的最后一个元素
db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )
// $elemMatch, $slice 和 $ 是唯一能控制数组返回字段的方法,在这里,不可以使用类似于:{ 'instock.0': 1 }这种控制只显示instock数组的第一个元素的。
如何显示null或者缺失字段
// 示例数据
db.inventory.insertMany([
{ _id: 1, item: null },
{ _id: 2 }
])
// item设为null时,会返回null,以及不存在该字段的数据,比如第二条数据不存在item字段,也会被返回
db.inventory.find( { item: null } )
// 结果为:
{ "_id" : 1, "item" : null }
{ "_id" : 2 }
// 如果想要精确匹配,可以这样:
// 10 是Null类型的数值表示,具体可看:https://docs.mongodb.com/manual/reference/bson-types/,里面有各种类型对应的数值
db.inventory.find( { item : { $type: 10 } } )
// 结果为:
{ "_id" : 1, "item" : null }
// 还可以使用$exists操作符,用于标明字段是否存在
db.inventory.find( { item : { $exists: false } } )
// 结果为:
{ "_id" : 2 }
// 如果$exists设为true,则返回:
{ "_id" : 1, "item" : null }
使用游标操作数据
// 可以将find的返回值保存到一个变量中
var myCursor = db.users.find( { type: 2 } );
while (myCursor.hasNext()) {
print(tojson(myCursor.next()));
}
// 可以使用printjson代替print(tojson()
var myCursor = db.users.find( { type: 2 } );
while (myCursor.hasNext()) {
printjson(myCursor.next());
}
// 还可以使用游标的forEach方法
var myCursor = db.users.find( { type: 2 } );
myCursor.forEach(printjson);
游标对象的具体有哪些方法可以看:docs.mongodb.com/manual/refe…
更新数据
更新数据主要使用:
db.collection.updateOne(<filter>, <update>, <options>)db.collection.updateMany(<filter>, <update>, <options>)db.collection.replaceOne(<filter>, <update>, <options>)
mongodb提供了更新操作符去更新数据,比如$set,具体可看文档:docs.mongodb.com/manual/refe…
有一些操作符,比如$set在字段不存在时会自动添加该字段
// 示例数据
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" }
] );
// 第一个参数这里也不继续说明了,详细可以看上面查询部分
/*
** 1. 更新size的uom字段值为cm
** 2. 更新status字段值为P
** 3. 更新lastModified为当前时间,如果lastModified字段不存在,会添加该字段
*/
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)
// 更新后的数据:
{ "_id" : ObjectId("5e6466a4940e1ec922af0d5b"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2020-03-08T03:29:48.653Z") }
// 更新多条数据
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)
/*
** 替换数据
** 1. _id字段不能被替换,如果新数据里包含_id字段,则值必须和原数据的一致
** 2. 新数据不能包含操作符
*/
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
upsert属性
如果updateOne(), updateMany() 或者 replaceOne()包含upsert: true参数时,如果这三个方法没有匹配到任何文档,则会创建一个新的插入到集合中,如果匹配到了,则会修改或者替换原文档。
使用聚合更新数据
在聚合中可以使用一下更新操作符:
- $addFields
- $set
- $project
- $unset
- $replaceRoot
- $replaceWith
// 示例数据
db.students.insertMany([
{ _id: 1, test1: 95, test2: 92, test3: 90, modified: new Date("01/05/2020") },
{ _id: 2, test1: 98, test2: 100, test3: 102, modified: new Date("01/05/2020") },
{ _id: 3, test1: 95, test2: 110, modified: new Date("01/04/2020") }
])
/*
** updateOne方法第二个参数可以是以数组,里面可以有多种操作
** 1. 新增一个test3字段并设为98
** 2. 修改modified数据值为当前时间
*/
db.students.updateOne( { _id: 3 }, [ { $set: { "test3": 98, modified: "$$NOW"} } ] )
// 示例数据
db.students2.insertMany([
{ "_id" : 1, quiz1: 8, test2: 100, quiz2: 9, modified: new Date("01/05/2020") },
{ "_id" : 2, quiz2: 5, test1: 80, test2: 89, modified: new Date("01/05/2020") },
])
/*
** 同时执行多个操作,首先序列化所有文档(集合中的每个文档字段可能并不一致),再更新modified字段
** 1. 序列化文档,如果文档中没有 quiz1 or quiz2 or test1 or test2 就给它添加该字段,并将值设为0。该操作可以用于将集合中所有文档的字段保持一致
** 2. 更新文档的modified为当前时间
*/
db.students2.updateMany( {},
[
{ $replaceRoot: { newRoot:
{ $mergeObjects: [ { quiz1: 0, quiz2: 0, test1: 0, test2: 0 }, "$$ROOT" ] }
} },
{ $set: { modified: "$$NOW"} }
]
)
// 结果为:
{ "_id" : 1, quiz1: 8, quiz2: 9, test1: 0, test2: 100, modified: new Date("01/05/2020") }
{ "_id" : 2, quiz1: 0, quiz2: 5, test1: 80, test2: 89, modified: new Date("01/05/2020") }
// 示例数据
db.students3.insert([
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "modified" : ISODate("2019-01-01T00:00:00Z") }
]);
/*
** 设置average, grade字段值,并且修改modified值
** 1.1 设置average字段(如果没有会新增)为tests数组的平均值,0代表保留0个小数,即取证,具体可看$trunc操作符文档https://docs.mongodb.com/manual/reference/operator/aggregation/trunc/
** 1.2 设置modifed字段为当前时间
** 1 设置grade字段,根据average的值分别设为A,B,C,D,F
*/
db.students3.updateMany(
{ },
[
{ $set: { average : { $trunc: [ { $avg: "$tests" }, 0 ] }, modified: "$$NOW" } },
{ $set: { grade: { $switch: {
branches: [
{ case: { $gte: [ "$average", 90 ] }, then: "A" },
{ case: { $gte: [ "$average", 80 ] }, then: "B" },
{ case: { $gte: [ "$average", 70 ] }, then: "C" },
{ case: { $gte: [ "$average", 60 ] }, then: "D" }
],
default: "F"
} } } }
]
)
// 结果为:
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "average": 92, "grade": "A", "modified" : ISODate("2019-01-01T00:00:00Z") }
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "average": 90, "grade": "A", "modified" : ISODate("2019-01-01T00:00:00Z") }
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "average": 75, "grade": "C", "modified" : ISODate("2019-01-01T00:00:00Z") }
// 示例数据
db.students4.insertMany([
{ "_id" : 1, "quizzes" : [ 4, 6, 7 ] },
{ "_id" : 2, "quizzes" : [ 5 ] },
{ "_id" : 3, "quizzes" : [ 10, 10, 10 ] }
])
// 在quizzes后追加[8, 6]
db.students4.updateOne( { _id: 2 },
[ { $set: { quizzes: { $concatArrays: [ "$quizzes", [ 8, 6 ] ] } } } ]
)
// 结果为
{ "_id" : 2, "quizzes" : [ 5, 8, 6 ] }
// 示例数据
db.temperatures.insertMany([
{ "_id" : 1, "date" : ISODate("2019-06-23"), "tempsC" : [ 4, 12, 17 ] },
{ "_id" : 2, "date" : ISODate("2019-07-07"), "tempsC" : [ 14, 24, 11 ] },
{ "_id" : 3, "date" : ISODate("2019-10-30"), "tempsC" : [ 18, 6, 8 ] }
])
/*
** 1. 新增tempsF字段
** 2. 将tempsC数组里的摄氏度转换为华氏度 f = c * 1.8 + 32
*/
db.temperatures.updateMany( { },
[
{ $addFields: { "tempsF": {
$map: {
input: "$tempsC",
as: "celsius",
in: { $add: [ { $multiply: ["$$celsius", 9/5 ] }, 32 ] }
}
} } }
]
)
// 结果为:
{ "_id" : 1, "date" : ISODate("2019-06-23"), "tempsC" : [ 4, 12, 17 ], "tempsF": [39.2, 53.6, 62.6] }
{ "_id" : 2, "date" : ISODate("2019-07-07"), "tempsC" : [ 14, 24, 11 ], "tempsF": [57.2, 75.2, 51.8] }
{ "_id" : 3, "date" : ISODate("2019-10-30"), "tempsC" : [ 18, 6, 8 ], "tempsF": [64.4, 42.8, 46.4] }
update方法
具体可看文档:docs.mongodb.com/manual/refe…
-
db.collection.updateOne() -
db.collection.updateMany() -
db.collection.replaceOne() -
db.collection.update() -
db.collection.findOneAndReplace() -
db.collection.findOneAndUpdate() -
db.collection.findAndModify() -
db.collection.save() -
db.collection.bulkWrite()
删除数据
可以使用下面方法删除数据
db.collection.deleteMany()db.collection.deleteOne()
// 示例数据
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ 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" },
] );
// 删除inventory所有数据
db.inventory.deleteMany({})
// 删除所有匹配的数据
db.inventory.deleteMany({ status : "A" })
// 删除匹配到的第一条数据
//db.inventory.deleteOne( { status: "D" } )
删除操作不会删除索引,即使删掉所有文档