mongodb--介绍与基本使用(笔记)二

1、MongoDB是什么

  • 存储文档的非关系型数据库 (非关系--表格不固定,新增加文档结构,直接存入也不会报错)
  • 其它非关系型数据库:redis、cassandra、objectivity、neo4j

2、运行mongodb 基本设置

  • 下载运行 
# 使用docker运行MongoDB
# 下载镜像
dcker pull mongo:4

# 查看镜像
docker images

# 启动MongoDB
# 容器名称:mymongo,挂着数据目录:-v,后台启动:-d
docker run --name mymongo -v /mymongo/data:/data/db -d mongo:4

# 查看启动日志
docker logs mymongo
  • 安装mongodb数据库管理器
# 下载mongo-express镜像
docker pull mongo-express

# 运行mongo-express
docker run --link mymongo:mongo -p 8081:8081 mongo-express
  •  localhost:8081 进入管理界面
  • 自动创建三个系统数据库  不建议修改他们 

3、基本命令

3.1进入docker 中mongo命令行界面

  • docker exec -it mymongo mongo
  • mongo shell 是javascript客户端界面,可以使用js命令。
  • exit 退出界面
  • 创建表

3.2主键 _id

  • 唯一性、支持所有数据类型(数组除外)、复合主键
  • 对象主键 ObjectId 官方的一种创建方式,不设置主键自动创建,快速生成12字节Id,包含创建时间
  • 提取主键里的时间 
  • 复合主键
    • db.accounts.insert(
          {
              _id: { accountNo: "007",type: "cat"},
              name: "gray",
              balance: 100
          }
      )
      

       

3.3创建库 

# 使用数据库(没有回创建数据库)
use test

# 查看数据库中的表
show collections

3.4创建表 insertOne

格式: writeConcern 是设置安全级别。用来判断一次写入操作是否成功,安全级别越高,丢失数据风险越低,写入延迟风险也可能越高。

# 这里自动创建了 accounts 表
# 如果这里不设置主键,会默认生成主键
db.accounts.insertOne(
    {
        _id: "account1",
        name: "alice",
        balance: 100
    }
)

# 返回消息 true 表示安全写级别被启用
# 由于我们在创建命令中没有设置writeConcern 这里显示的是默认开启的安全写级别启用状态
# insertedId 显示了写入的文档id
{"acknowledged": true, "insertedId" : "account1"}

3.5创建多个文档

ordered 是否按照顺序写入。true如果 前面有执行错误,则后面的文档会添加失败。false 则只会是报错的文档添加失败

db.accounts.insertMany(
    {
        name: "charlie",
        balance: 100
    },
    {
        name: "david",
        balance: 50
    }
)

insert & save 

db.accounts.insert(
    {
        name: "gray",
        balance: 100
    },
    {
        name: "cat",
        balance: 50
    }
)

# 返回消息
WriteResult({"ninserted":1})

# 这个也是创建文档,内部是调用的insert命令
db.accounts.save(
    {
        name: "gray2",
        balance: 100
    },
    {
        name: "cat2",
        balance: 50
    }
)

insert支持db.collection.explain()命令,另外insertMany和insertOne是不支持的。

3.6读取表

# 比较操作符
$eq 相等
$ne 不等
$gt 大于
$gte 大于等于
$lt 小于
$lte 小于等于

$in 在这个范围内查找
$nin 查找不在这个范围内的文档

$not 否定判断
$and 并列条件判断
$or  或者
$nor 既不要,也不要

$exists 匹配包含查询字段的文档
$type 匹配字段类型符合查询值的文档

$all 匹配包含数组字段的文档
$elemMatch 查询包含数组字段其中一个的文档

$regex 匹配正则表达式
# 读取alice的文档,且账户余额100
db.accounts.find({name: "alice",balance: 100})
# 和上面效果一样
db.accounts.find({name: {$eq:"alice"},balance: 100})

# 读取复合主键中 type = save的文档
db.accounts.find({"_id.type": "save"})
# 读取不属于alice 的文档
db.accounts.find({name:{ $ne: "alice"}})

# 复合查询 这样会把主键里没有type字段的也全部查出来
db.accounts.find({"_id.type":{ $ne: "save"}})
# 这样就只会在主键包含type的地方查询
db.accounts.find({"_id.type":{ $ne: "save",$exists: true}})

# 读取主键是字符串的文档
db.accounts.find({_id:{ $type: "string"}})
# 读取主键是 对象主键或者是复合主键的文档
db.accounts.find({_id:{ $type: ["objectedId","object"]}})
# 查询用户名是类型 null的文档
db.accounts.find({name:{ $type: "null"}})

# 查询用户名是alice或者charlie的文档
db.accounts.find({name:{ $in: ["alice","charlie"]}})

# 查询余额不小于500的账户文档
db.accounts.find({balance:{ $not: {$lt: 500}}})

# 查询余额大于100并且用户名排在fred之后的文档
db.accounts.find({
                $and:[
                    {balance: {$gt:100}},    
                    {name:{$gt:"fred"}}
                 ]})
# 筛选条件用在不同字段上,可以省略 $and
db.accounts.find({
                    balance: {$gt:100},    
                    name:{$gt:"fred"}
                 })
# 筛选条件在同一个字段上,可以简化命令
db.accounts.find({ balance: {$gt:100,$lt: 500} })

# 查询用户名是alice或者fred的文档
db.accounts.find({
                $or:[
                    {name: {$eq:"alice"}},    
                    {name:{$eq:"fred"}}
                 ]})
# 读取用户名不属于alice也不属于charlie,且余额小于100的文档
db.accounts.find({
            $nor: [
                {name: "alice"},
                {name: "charlie"},
                {balance: {$lt: 100}}
            ]
})

# 查询地址位于中国北京的文档
db.accounts.find({address: {$all: ["China","BeiJing"]}})
# 读取电话号码在10000到20000的文档
db.accounts.find({photo: {$elemMatch: {$gt: "10000",$lt: "20000"}}})
# all和elemMatch 一起使用
# 查找电话号码在15000到20000的文档
db.accounts.find({
                photo: {$all: [
                           $elemMatch: {$gt: "10000",$lt: "20000"}, 
                           $elemMatch: {$gt: "15000",$lt: "50000"},
                        ]}
                })
# 读取用户名以c或者j开头的文档
db.accounts.find({name: {$in: [/^c/,/^j/]}})

# 读取用户名包含LIE(不区分大小写)的文档,($options:'i' 不区分大小写)
db.accounts.find({name: {$regex: /LIE/,$options:'i'}})

3.7读取表(游标)

# 获取所有表
# 遍历完myCursor或者10分钟后 myCursor就会失效!!
var myCursor = db.accounts.find();
# 获取第一张表
myCursor[0]

# noCursorTimeout 设置myCursor 一直有效。用完后的主动关闭
var myCursor = db.accounts.find().noCursorTimeout();
# 关闭游标
myCursor.close()
# 游标函数
cursor.hasNext()
cursor.next()
cursor.forEach()
cursor.limit()
cursor.skip()
cursor.count()
cursor.sort() # 1表示由小及大排序,-1表示逆向排序
# 迭代
var myCursor = db.accounts.find({name:"grorge"}).noCursorTimeOut;
while(myCursor.hasNext()){
    printjson(myCursor.next());
}

#循环遍历
myCursor.forEach(printjson)
myCursor.close()
# 查询用户george的第3到6篇文档(排除前2篇后选择前面4篇)
db.accounts.find({name:"george"}).skip(2).limit(4)
# 会显示george的全部文档
db.accounts.find({name:"george"}).limit(0)

# limit、skip与count一起使用时,需要设置count(true)
# 这个会显示george的全部文档数量
db.accounts.find({name:"george"}).limit(1).count()
# 这个才会显示数量1
db.accounts.find({name:"george"}).limit(1).count(true)

当数据库分布式机构较为复杂时,元数据中的文档数量可能不准确,在这种情况下,应当避免使用不提供筛选条件的cursor.count()函数。而使用聚合管道来计算文档数量。

# 用户余额从大到小,用户名按照字母排序的方式显示
db.zccounts.find().sort({balance: -1,name: 1})

# skip会自动在 limit之前执行
# sort 会自动在limit和skip之前执行
# 显示排除前三条后的5条数据
db.accounts.find().limit(5).skip(3)

3.7读取表(投射)

  • 不是同投射,返回反正文档数据
  • 1表示返回字段,0表示不返回字段
  • 除了主键,我们不能再投影文档中混合使用包含和不包含这两种投影操作
# 查询文档,直返回用户名,默认主键会自动返回
db.accounts.find({},{name:1})

# 想不要主键
db.accounts.find({},{name: 1,_id: 0})

# 除了name和balance 其他字段都返回
db.accounts.find({},{name: 0,balance: 0})

# 显示name和contact 参数。contact只显示数组中的第一个
db.accounts.find({},{name: 1,contact: {$slide: 1}})
# 显示name和contact 参数。contact只显示数组中的前2个
db.accounts.find({},{name: 1,contact: {$slide: 2}})
# 显示name和contact 参数。contact只显示数组中的最后2个
db.accounts.find({},{name: 1,contact: {$slide: -2}})
# 显示name和contact 参数。contact只显示数组中,排除第一个后的前2个,skip 1, limit 2
db.accounts.find({},{name: 1,contact: {$slide: [1,2]}})

# elemMatch和$操作符可以返回数组字段中满足筛选条件的第一个元素
db.accounts.find({},
                    { _id:0 ,name:1,
                        contact: {$elemMatch: {$gt: "Alabama"}}
                    })
# 同上效果,一行是条件,第二行是显示内容
db.accounts.find(
                {contact: {$gt: "Alabama"}},
                { _id:0 ,name:1,"contact.$": 1}
            )

3.8更新表 update 更新整篇文档

  • 一共是可以传三个数据的 
  • 文档主键_id 是不可修改的,如果非要在修改信息中包含主键,一定要和被修改的主键一致。
# 把找到的名字是alice的第一篇文档,更新成下面数据
db.account.update({name: "alice"},balance : 123)

3.9更新表 update 更新特定字段

# $set
# 找到jack的第一个文档,更新信息
db.accounts.update(
    {name: "jack"},
    {$set:
        {
            balance: 3000,
            info: {
                dateOpened: "hello",
                branch: "branchl"}
        }        
    }
)

# 更新文档内数组信息
db.accounts.update(
    {name: "jack"},
    {$set:
        {
            "contact.0": "6666666"
        }        
    }
)
# $unset删除字段 , "" 内设置任何值都没影响,都是清空
db.accounts.update(
    {name: "jack"},
    {$unset:
        {
            balance: "",
            "info.branch": "",
        }        
    }
)
# 删除集合内元素
db.accounts.update(
    {name: "jack"},
    {$unset:
        {
            "contact.0": ""
        }        
    }
)

$rename命令中的旧字段和新字段都不可用指向数组 元素。

# $rename 重命名,如果集合内字段不存在,那么文档内容不会改变。
# $rename命令会先$unset旧字段然后在$set新字段
db.accounts.update(
    {name: "jack"},
    {$rename:
        {
            "info.branch": "branch",
            "balance": "info.balance"
        }        
    }
)

# 如果字段不存在,$inc会创建字段,并将字段加减设置中的值。$mul会创建字段,然后设置成0
# 表david 中的balance减少0.5
db.accounts.update(
    {name: "david"},
    {$inc:
        {
            "balance": -0.5
        }        
    }
)
# 表david 中的balance乘以0.5
db.accounts.update(
    {name: "david"},
    {$mul:
        {
            "balance": 0.5
        }        
    }
)

# 如果被更新的值不存在,会创建值,并把设置的值赋值进去。
# 设置参数与原始参数比较,选择较大的留下(即便类型不是数字,会用编码大小判断)
# 大小顺序判断 Null < Number < Symbol,String < Object < Array < BinData < ObjectId < Boolean < Date < Timestamp < Regular Expression
db.accounts.update(
    {name: "david"},
    {$max:
        {
            "balance": 500
        }        
    }
)
# 设置参数与原始参数比较,选择较小的留下
db.accounts.update(
    {name: "david"},
    {$min:
        {
            "balance": 50
        }        
    }
)

3.10更新表 文档更新操作符

$set    更新或新增字段
$unset    删除字段
$rename    重命名
$inc    加减字段
$mul    相乘字段
$min    设置参数与原始参数比较,选择较小的留下
$max    设置参数与原始参数比较,选择较大的留下

3.11更新表 数组更新操作符

$addToSet 向数组元素中添加字段
$push 向数组中添加元素(没有会新添加) 功能更强大
$pop 删除数组元素
$pull 删除数组元素(匹配一部分就行)
$pullAll 完全匹配删除(字段值和顺序都需要匹配)
$[] 指数组中的所有元素
# 如果插入值已经在数组字段中,则不会重复添加。(如果字段顺序不一样,不算重复)
# 向karen的文档中添加联系方式
db.accounts.update(
    {name: "karen"},
    {$addToSet: {contact: "China"}}
)

# 一次添加多个元素each
db.accounts.update(
    {name: "karen"},
    {$addToSet: {contact: {$each: ["contactl","contactl2"]}}}
)

# $pop只能用在数组字段上
# 删除contact中的最后一个元素
db.accounts.update(
    {name: "karen"},
    {$pop: {contact: 1}}
)
# contact.5 本身也是个数组,设置contact第6个数组中第一个参数为null
db.accounts.update(
    {name: "karen"},
    {$pop: {contact.5: -1}}
)

# 从update中删除包含"hi"字母的元素
db.accounts.update(
    {name: "karen"},
    {$pull: {contact: $regex: /hi/}}
)
# 也可以使用$elemMatch
# karen中删除电话号码222222
db.accounts.update(
    {name: "karen"},
    {$pull: {contact: {$elemMatch: {$eq: "222222"}}}}
)
# 完全匹配删除,数组得写完
db.accounts.update(
    {name: "karen"},
    {$pullAll: {contact: [["222222","333333"]]}}
)

复制表

ad.accounts.find(
    {name: "karen"}, #找到karen这张表
    {_id: 0} # 显示除主键意外其他字段
).forEach(function(doc){
        var newDoc = doc; #获取查询到的表
        newDoc.name = "lawrence"; #修改名称、
        db.accounts.insert(newDoc);  # 存入新的表
    }
)
# 和each搭配使用,一次添加多个
db.accounts.update(
    {name: "lawrence"},
    {$push: {
        newArray: {
            $each: [2,3,4]
        }
    }}
)
# 只想截取集合中元素
db.accounts.update(
    {name: "lawrence"},
    {$push: {
        newArray: {
            $each: [],
            $slice:5
        }
    }}
)

# 执行顺序固定 $position > $sort > $slice
# 元数据第二个位置插入新字段,排序后取5个保留
db.accounts.update(
    {name: "lawrence"},
    {$push: {
        newArray: {
            $each: ["push1","push2","push3"],
            $slice:5,
            $position: 2,
            $sort: -1
        }
    }}
)

# 使用.$ 代替上面使用的查询
# newArray.$ 值 newArray = "pos2" 的值改成"updated"
db.accounts.update(
    {name: "lawrence",
        newArray: "pos2"
    },
    {$set: {
        "newArray.$": "updated"
    }
)

# contact 中第一个位置的数组,里面所有元素改成888888
db.accounts.update(
    {name: "lawrence"},
    {$set: {
        "contact.0.$[]": "888888"
    }
)

3.12更新表 update 更新多篇文档

 Mongodb只能保证单个文档操作原子性,不能保证多个文档一起修改原子性。(使用事务功能才行)

# multi: true 同上更新多篇文档
# 设置所有文档currency = USD
db.accounts.update(
    {},
    {$set: {
            currency: "USD"
        }
    },
    {multi: true}
)

# upsert:<boolean> 更新或创建文档
# 文档有会赋值,没有会创建新的(会包含name和balance两字段和值)
db.accounts.update(
    {name: "maggie"},
    {$set: {balance: 800}},
    {upsert: true}
)
# 但是字段是不确定的,则这个字段不会创建。(只会包含balance字段和值)
db.accounts.update(
    {balance: {$gt: 20000}},
    {$set: {balance: 800}},
    {upsert: true}
)

3.13更新表 save 更新文档

# 底层调用的还是update()并且upsert: true
db.accounts.save(
    {balance: 200,name: "animal"}
)

4.14删除表 remove()

# 默认情况,remove会删除所有符合筛选条件的文档
# 删除余额为50的账户文档
db.accounts.remove({balance: 50})

# 如果只想删除找到的第一篇文档
db.accounts.remove({balance: 50},{justOne: true})

4.15删除集合 drop()

# 如果数据非常多,需要清空集合,就直接删除集合。重新创建新集合。
# 删除整个accounts集合
db.accounts.drop()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值