文章来自
MongoDB的基本用法
mongodb命令行操作
菜鸟教程
官方文档,需要英语阅读能力
mongodb和mysql的区别
- mysql是一个电脑有很多个数据库【show databases】,一个数据库里有很多表【user表】,一个表里有很多数据【一行就是一条数据】,一条数据是以多个key-value组成的;
- mongodb是一个电脑有很多数据库【show dbs】,一个数据库里有很多集合【collection】,一个集合有很多文档,一个集合是以多个key-value组成的;
# 查看当前所在数据库
db
# 使用数据库
use db_name
# 删除数据库
db.dropDatabase() # 删除当前正在使用的数据库
# 使用集合
db.collection_name.find() # 查所有满足条件数据
db.collection_name.count() # 统计集合下面有多少数量的数据
# 删除集合
db.collection_name.drop()
# 创建数据库和集合
# 当你使用一个不存在的mongo数据库时,就自动创建了一个mongo数据库
# 同理当你往一个空集合里面插入了一条数据之后就自动创建了一个集合
# 查看当前数据库状态
db.stats()
# 查看当前数据库版本
db.version()
# 备份数据库
# 导出
mongodump --host IP --port 端口 -u 用户名 -p 密码 -d 数据库 -o 文件路径
# 导入
mongorestore --host --port -d 文件路径
mongo中的操作符
$set // 更新字段
$unset // 删除字段
$inc // 自增 {$inc: {money: 10}} | 自减 {$inc: {money: -10}}
$exists // 是否存在
$in // 是否在...范围
$and
$or
$push // 向数组中尾部添加一个元素
$addToSet // 向集合中添加元素
$pop // 删除数组中的头部或尾部元素
插入数据之insert
db.users.insert({"name": "mengdee", "age": 20})
// 多条写成数组
db.users.insert([{"username": "mengday4"}, {"username": "mengday5"}])
// 可以自定义id
// 不指定id 自动生成objID, 也可以指定插入
db.users.insert({"_id":1,"name":"nick"})
// 注意insert 在插入的时候如果已经存在了相同的id会报错
// 如果想要存在相同的id的时候不报错而是更新数据 请使用 save方法
更新数据之update
# 语法:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
// 示例1 例如,给定一个books包含以下文档的集合:
{
_id: 1,
item: "TBD",
stock: 0,
info: { publisher: "1111", pages: 430 },
tags: [ "technology", "computer" ],
ratings: [ { by: "ijk", rating: 4 }, { by: "lmn", rating: 5 } ],
reorder: false
}
# 更新部分字段,指定id
db.books.update(
{ _id: 1 },
{
$inc: { stock: 5 }, # 自增或者自减,整数为负值 就是自减
$set: { # set 是更新部分字段
item: "ABC123",
"info.publisher": "2222",
tags: [ "software" ],
"ratings.1": { by: "xyz", rating: 3 }
}
}
)
// 更新结果
{
"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : { "publisher" : "2222", "pages" : 430 },
"tags" : [ "software" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],
"reorder" : false
}
# 更新全部字段
db.books.update(
{ item: "XYZ123" },
{
item: "XYZ123",
stock: 10,
info: { publisher: "2255", pages: 150 },
tags: [ "baking", "cooking" ]
}
)
// 更新结果
{
"_id" : 2,
"item" : "XYZ123",
"stock" : 10,
"info" : { "publisher" : "2255", "pages" : 150 },
"tags" : [ "baking", "cooking" ]
}
# 更新的时候如果数据不存在就插入insert
db.books.update(
{ item: "ZZZ135" },
{
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
},
{ upsert: true }
)
//更新结果
{
"_id" : ObjectId("542310906694ce357ad2a1a9"),
"item" : "ZZZ135",
"stock" : 5,
"tags" : [ "database" ]
}
# 更新多个文件需要设置multi为true
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
)
# upsert 和 multi 结合使用
// 给定下面的文档
{
_id: 5,
item: "EFG222",
stock: 18,
info: { publisher: "0000", pages: 70 },
reorder: true
},
{
_id: 6,
item: "EFG222",
stock: 15,
info: { publisher: "1111", pages: 72 },
reorder: true
}
// 更新
db.books.update(
{ item: "EFG222" },
{ $set: { reorder: false, tags: [ "literature", "translated" ] } },
{ upsert: true, multi: true }
)
// 更新结果
{
"_id" : 5,
"item" : "EFG222",
"stock" : 18,
"info" : { "publisher" : "0000", "pages" : 70 },
"reorder" : false,
"tags" : [ "literature", "translated" ]
},{
"_id" : 6,
"item" : "EFG222",
"stock" : 15,
"info" : { "publisher" : "1111", "pages" : 72 },
"reorder" : false,
"tags" : [ "literature", "translated" ]
},{ // 如果没有匹配的文档就会插入文档
"_id" : ObjectId("5423200e6694ce357ad2a1ac"),
"item" : "EFG222",
"reorder" : false,
"tags" : [ "literature", "translated" ]
}
# 更新数组
// 现有以下数据
db.students.insert([
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
])
// 更新下面数据
db.students.update(
{ grades: { $gte: 100 } },
{ $set: { "grades.$[element]" : 100 } },
{
multi: true,
arrayFilters: [ { "element": { $gte: 100 } } ]
}
)
// 更新结果
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }
# 更新数组中的字典
// 现有以下数据
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
// 更新语句
db.students2.update(
{ },
{ $set: { "grades.$[elem].mean" : 100 } },
{
multi: true,
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
}
)
// 更新结果
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}
# 删除字段使用$unset
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "age" : 18 }
db.users.update({"username": "mengday5"}, {"$unset": {"age": 1}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456" }
# $push: 向数组的尾部添加一个元素,如果字段不存在则创建
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm" ] }
db.users.update({"username": "mengday5"}, {"$push": {"hobby": "money"}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money" ] }
# $push + $each : 批量push
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money" ] }
db.users.update({"username": "mengday5"}, {"$push": {"hobby": {"$each": ["play", "eat"]}}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat" ] }
# $pushAll = $push + $each 批量push
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat" ] }
db.users.update({"username": "mengday5"}, {"$pushAll": {"hobby": ["drink", "happy"]}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat", "drink", "happy" ] }
# $addToSet:不重复的set集合
{ "_id" : 1, "username" : "mengday5", "password" : "123456" }
db.users.update({}, {"$addToSet": {"hobby": "eat"}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
# $addToSet和$push
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
db.users.update({}, {"$addToSet": {"hobby": {"$each": ["eat", "drink"]}}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat", "drink" ] }
# $pop: 弹出数组的头部元素或尾部元素: -1:头部,1:尾部
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat", "drink" ] }
db.users.update({}, {"$pop": {"hobby": 1}})
{ "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
# $pull: 删除数组中的值
db.lists.insert({"no": [1, 1, 1, 3]})
db.lists.update({}, {"$pull": {"no": 1}})
{ "_id" : ObjectId("597c0a3087d089dfa7ce1be2"), "no" : [ 3 ] }
# 使用小标或者定位操作符【$】来操作数组
{ "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
"username" : "mengday",
"addresses" : [
{ "city" : "shanghai", "area" : "zhangjiang" },
{ "city" : "beijing", "area" : "chaoyang" }
]
}
// 修改内嵌文档数组中第二个元素的值
db.users.update({"username": "mengday"}, {"$set": {"addresses.1.area": "chaoyangqu"}})
{
"_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
"username" : "mengday",
"addresses" : [
{
"city" : "shanghai",
"area" : "zhangjiang"
},
{
"city" : "beijing",
"area" : "chaoyangqu"
}
]
}
# 定位操作符【$】: 查询条件一般是以数组中的元素为条件,使用【$】符号作为满足查询条件的第一条文档对应的下标值
{
"_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
"username" : "mengday",
"addresses" : [
{
"city" : "shanghai",
"area" : "zhangjiang"
},
{
"city" : "beijing",
"area" : "chaoyangqu"
}]
}
db.users.update({"addresses.city": "beijing"}, {"$set": {"addresses.$.area": "CHAOYANG"}})
{
"_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
"username" : "mengday",
"addresses" : [
{
"city" : "shanghai",
"area" : "zhangjiang"
},
{
"city" : "beijing",
"area" : "CHAOYANG"
}]
}
# 更新数组
//准备数据
db.students.insert([
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
])
//更新语句
db.students.update(
{ grades: { $gte: 100 } },
{ $set: { "grades.$[element]" : 100 } },
{ arrayFilters: [ { "element": { $gte: 100 } } ] }
)
//更新结果
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
# 更新数组中的字典
db.students2.insert([
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
])
db.students2.update(
{ },
{ $set: { "grades.$[elem].mean" : 100 } },
{ arrayFilters: [ { "elem.grade": { $gte: 85 } } ] }
)
// 注意只有_id 为1 的被更新了, 因为是updateOne操作
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
mongo运算符
$eq 等于 {<key>:<value>}
$ne 不等于 {<key>:{$ne:<value>}}
$gt 大于 {<key>:{$gt:<value>}}
$gte 大于等于 {<key>:{$gte:<value>}}
$lt 小于 {<key>:{$lt:<value>}}
$lte 小于等于 {<key>:{$lte:<value>}}
$in 在范围内
$nin 不在范围内
查询数据之find
# 查询所有
db.users.find()
# pretty() 用于格式化查询的结果
db.users.find().pretty()
# 查询条件, 相当于 select * from users where age < 20
db.users.find({"age": {$lt: 20}})
# 查询指定的字段,1:代表要查询的字段,0:代表不要查询的字段 ,相当于 select username, age from users where age < 20
db.users.find({"age": {$lt: 20}}, {"_id":0, "username": 1, "age": 1})
# and 条件,多个条件直接用逗号分开,不需要什么操作符: 相当于 select * from users where age < 20 and id < 3
db.users.find({"age": {$lt: 30}, "_id": {$lt: 3 }})
# 同一个字段多个条件: 相当于 select * from users where age > 25 and age < 30
db.users.find({"age": {$gt: 25, $lt:30 }})
# or: 相当于 select * from users where age > 30 or username = 'tom'
db.users.find({$or: [{"age": {$gt: 30}}, {"username": "tom"}]})
# and or 混合使用,相当于 select * from users where id < 4 and (username = 'mengdat' or age < 20)
db.users.find({ $or: [{"username": "mengday"}, {"age": {$lt: 20}}], "_id": {$lt: 4} })
# in: 相当于 select * from users where age in (18, 28)
db.users.find({"age": {$in: [18, 28]}})
# 正则表达式不但可以匹配字符串还可以匹配字段值是正则表达式类型的,此时是相等匹配
// 模糊查询,正则表达式: 以xiao开头,以ng结尾
// 相当于 select * from users where username like 'xiao%' and username like '%ng'
db.users.find({"username": /^xiao/, "username": /ng$/})
# 正则表达式忽略大小写
db.users.find({"username": {$regex:/sunday/, $options:"$i"}})
# 正则表达式用于数组
db.users.find({"hobby": {$regex: "mm"}})
# 正则表达式包含变量时需要使用eval()函数来计算
var username = "sunday"
db.users.find({"username": {$regex:eval("/" + username + "/i")}})
# 数组字段: 值,意思就是这个数组中是否包含该元素,如果包含就是满足条件的
db.food.insert({"fruit": ["apple", "banana", "cherry"]})
db.food.find({"fruit": "banana"})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
# 当值是一个值时是是否包含,当值是数组时就是精确匹配了,此时匹配不到结果
db.food.find({"fruit": ["apple", "cherry"]})
// $all: 数组中同时都包含多个元素
db.food.find({"fruit": {$all: ["apple", "cherry"]}})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
# 查询数组中指定的下标对应的值是否和给的值一样
// 查询文档中的fruit中第三个元素的值是cherry的文档
db.food.find({"fruit.2": "cherry"})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
# $size: 根据数组的长度进行筛选
db.food.find({"fruit": {$size: 3}})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
# 返回数组中前两个元素
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "orange", "cherry"] }
db.food.find({}, {"fruit": {$slice: 2}})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana" ] }
# 返回数组中后两个元素
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "orange", "cherry"] }
db.food.find({}, {"fruit": {$slice: -2}})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "orange", "cherry" ] }
# 偏移下标为1,取2个长度,相当于 limint 0, 2
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "orange", "cherry"] }
db.food.find({}, {"fruit": {$slice: [1, 2]}})
{ "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "banana", "orange" ] }
# $elemMatch: 数组中是否有一个元素同时满足所有条件(只要有一个元素满足就能匹配上)
{ "_id" : ObjectId("597d4342e210addac88b2a37"), "x" : [ 2, 5 ] }
{ "_id" : ObjectId("597d4350e210addac88b2a38"), "x" : [ 4, 5 ] }
{ "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
db.test.find({"x": {"$elemMatch": {$gt: 5, $lt: 20}}})
{ "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
# 根据字段的数据类型来查询
db.users.find({"username": {$type: 'string'}})
# 查询文档中没有username字段的或者username的值是null
db.users.find({"username": null})
# 查询文档中存在username字段,并且值是null, $in:[null]和username:null 一样的效果
db.users.find({"username": {$in: [null], $exists: true}})
{ "_id" : ObjectId("597c58f848c373e228a925a6"), "username" : null, "age" : 25 }
{ "_id" : ObjectId("597c591e48c373e228a925ab"), "username" : null, "age" : 24 }
# 自定义筛选条件,通过js函数返回的boolean值来筛选,可以实现复杂条件的筛选
db.users.find({$where:'this.username == "mengday"'})
// 或者
db.users.find({$where: function(){ return this.username == 'mengday' }})
{ "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
# $all匹配所有
// 这个操作符跟SQL 语法的in 类似,但不同的是, in 只需满足( )内的某一个值即可,
// 而$all 必须包含[ ]内的所有值,例如:
db.users.find({age : {$all : [6, 8]}});
// 可以查询出 {name: 'David', age: 26, age: [ 6, 8, 9 ] }
// 但查询不出 {name: 'David', age: 26, age: [ 6, 7, 9 ] }
# $exists判断字段是否存在
// 查询存在字段age 的数据
> db.c1.find({age:{$exists:true}});
{ "_id" : ObjectId("4fb4a773afa87dc1bed9432d"), "age" : 20, "length" : 30 }
# null值查询处理
db.c2.find({age:null})
{ "_id" : ObjectId("4fc34bb81d8a39f01cc17ef4"), "name" : "Lily", "age" : null }
{ "_id" : ObjectId("4fc34c1e1d8a39f01cc17ef6"), "name" : "Tom", "addr" : 23 }
//需要注意的是 不存在该字段的数据也被认为是null了,如果你不想这种数据返回,需要的字段值就是精确的null
//请使用exists限制一下
db.c2.find({age:{$exists:true,$eq:null}})
# $mod取模运算
// 查询age 取模10 等于0 的数据
db.student.find( { age: { $mod : [ 10 , 1 ] } } )
# $ne不等于
// 查询x 的值不等于3 的数据
db.things.find( { x : { $ne : 3 } } );
# $size 根据数组的长度进行查询
db.users.find({favorite_number: {$size: 3}});
// 能查询出下面的这条记录
{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }
// 但是就无法匹配,因为数组的长度不匹配
db.users.find({favorite_number: {$size: 2}});
# 正则表达式匹配查询
db.users.find({name:/^B.*/}); 匹配 name字段以 B开头的数据
db.users.find({name: {$not: /^B.*/}}); 匹配name字段不以B开头的数据
游标操作之skip
# 相当于mysql的 limit 3,5
// 限制查询的起始位置,和返回指定的数量的数据
db.users.find().skip(3).limit(5);
# 查询结果之排序sort
db.users.find().sort({age: 1}); // 以年龄升序排序
db.users.find().sort({age: -1}); // 以年龄降序排序
删除数据之remove
# 语法:
db.collection.remove(
<query>,
{
justOne: <boolean>,
}
)
# 语法详解
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
# 默认是删除多个
# 删除单个文档
该orders集合包含具有以下结构的文档:
{
_id: ObjectId("563237a41a4d68582c2509da"),
stock: "Brent Crude Futures",
qty: 250,
type: "buy-limit",
limit: 48.90,
creationts: ISODate("2015-11-01T12:30:15Z"),
expiryts: ISODate("2015-11-01T12:35:15Z"),
client: "Crude Traders Inc."
}
db.orders.remove( { "_id" : ObjectId("563237a41a4d68582c2509da") },{ justOne : true} );
查询数据的数量之count
# 无条件查询,相当于 db.orders.find().count()
db.collection.count()
其他
- 分组,聚合,去重的相关知识查看《分组查询》笔记
- 索引查看《mongodb索引》笔记
- 分片的知识暂时用不到,不学