mongodb数据库操做

安装在Ubuntu16.04:

# 建立数据库文件夹,这个是默认存放数据的地方,但MongoDB不会自动建立
mkdir -p /data/db
# 增长权限
chown -R $USER:$USER /data/db
wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | sudo apt-key add -  # 导入公钥
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list  # 为MongoDB建立列表文件
sudo apt-get update  # 从新加载本地数据包
sudo apt-get install -y mongodb-org=4.0.12 mongodb-org-server=4.0.12 mongodb-org-shell=4.0.12 mongodb-org-mongos=4.0.12 mongodb-org-tools=4.0.12  # 安装软件包
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections  # 保持目前的版本,防止自动更新
# 启动
sudo service mongodb start #或者
systemctl start mongodb

卸载

sudo apt-get purge mongodb-org*
sudo rm -r /var/log/mongodb
sudo rm -r /var/lib/mongodb

经过systemctl start mongodb 启动时的错误解决

报错以下:javascript

Failed to start mongodb.service: Unit mongodb.service not found.java

解决:正则表达式

sudo nano /etc/systemd/system/mongdb.service  # 建立服务文件
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf
# 制定须要执行的命令的位置,                                #  制定项目运行所须要的配置文件位置
[Install]
WantedBy=multi-user.target
  • 按ctrl + x 保存退出
  • systemctl start mongodb
  • 永久有效: systemctl enable mongodb

一、文档中值的数据类型

在mongodb中数据是以文档的形式存在的mongodb

一、每一个文档至关于一条记录shell

二、多个文档组合在一块儿,就是集合,一个集合就至关于一张数据表数据库

三、多个集合组合在一块儿,就是数据库,每一个数据库就是一个文件夹json

  • Object ID: ⽂档ID
  • String: 字符串, 最常⽤, 必须是有效的UTF-8
  • Boolean: 存储⼀个布尔值, true或false
  • Integer: 整数能够是32位或64位, 这取决于服务器
  • Double: 存储浮点值
  • Arrays: 数组或列表, 多个值存储到⼀个键
  • Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
  • Null: 存储Null值
  • Timestamp: 时间戳, 表示从1970-1-1到如今的总秒数
  • Date: 存储当前⽇期或时间的UNIX时间格式

二、Mongo shell

  • 使用mongo命令自动启动shell,并链接数据库服务器,该shell可以解析JavaScript的语法
  • 经过shell能够完成一些列的增删改查工做

三、文档的基本增删改查

  • 增长:使用insert()函数,将要插入的数据放到集合中ubuntu

    • 好比增长一个文档,首先先建立文档变量
post = {"title": "my first mongo"}
  • 插入文档到blog集合中
db.blog.insert(post)
    • 批量插入:一样适用inset方法,将你须要插入的文档所有存放到一个数组中
    • 当咱们链接到服务器以后,db会自动指向正在使用的数据库,blog为集合名,没有会自动建立
    • 查找:使用find()或者findOne()数组

      • find()默认显示20条数据
    db.blog.find()
    • findOne()只显示一条数据
    db.blog.findOne()
    • 更新:使用update()方法, 该方法接收两个参数,第一个为须要修改的文档,第二个修改过的文档

    update()方法除了接收前两个参数外,还能够接收另外两个参数,而且这两个参数都是布尔值bash

    例如:db.blog.update({"title": "My Blog Post"}, {"title": "My Blog Get"}, true, true)

    第三个参数表示upsert,可以保证操做的原子性,同时在没有查询到制定的集合状况下,会以查询条件和更新文档为基础新建一个文档,第四个参数默认是true,表示更新全部符合条件的集合,若改成false,则只更新第一个。

    • 第一:先更改文档对象的属性,也就是键值对,好比前文使用到的post变量
    给他增长一个属性:post.comments = []
    • 找到旧文档,替换为新的文档,根具给出的一个参数中的具体信息能够找到旧文档
    db.blog.update({"title":"my first mongo"}, post)
    • 删除:remove(),在不给出参数的状况下,删除集合中的全部文档,给出参数后,会删除对应的文档

      • db.blog.remove({"title":"my first mongo"})

    四、基于shell的其余命令,利用help查看

    > help
    db.help() help on db methods
    db.mycoll.help() help on collection methods
    sh.help() sharding helpers
    rs.help() replica set helpers
    help admin administrative help
    help keys key shortcuts
    help connect connecting to a db help
    help misc misc things to know
    help mr mapreduce
    show dbs show database names
    show collections show collections in current database
    show users show users in current database
    show profile show most recent system.profile entries with time >= 1ms
    show logs show the accessible logger names
    use <db_name> set current database
    db.foo.find() list objects in collection foo
    db.foo.find( { a : 1 } ) list objects in foo where a == 1
    it result of the last line evaluated; use to further iterate
    DBQuery.shellBatchSize = x set default number of items to display on shell
    exit quit the mongo shell

    五、访问集合

    一、当集合名与内置的函数名相同时,是没有办法经过db.集合名来访问的

    二、当集合名名包含-时,好比:six-four,一样没有办法经过正常的方法访问集合,引文shell对其的解释是两个变量的相减

    最终的解决办法是经过__getCollection()__来访问,例如:db.getCollection("version"),db.getCollection("six-four")这样才能正常访问

    六、save shell

    save是一个shell函数,能够在文档不存在的时候插入,存在的时候更新,它只有一个参数,即文档自己

    save会调用upsert,即实现文档的自动建立和更新

    var x = db.foo.findOne()

    x.num = 12

    db.foo.save(x)

    七、修改器,以$号开头的特殊字符串

    修改器 用法 做用
    $inc db.x.update({"a":1}, {$inc: {"b":1}}) 在原有b的基础上加1
    $set db.x.update({"a":1}, {$set: {"b":"a"}}) 将原有b的数据修改成a,若b不存在,则建立一个
    $unset db.x.update({"a":1}, {$unset: {"b":1}}) 撤销修改,此时的数值1,表示条件为真的意思
    $push db.x.update({"a":1}, {$push:{"comments": {"name":"json"}}}) 该修改器只做用于数组,能够向文档中已有数组中添加值,固然数组不存在时,建立一个数组并添加对应内容
    $pop db.x.update({"a":1}, {$pop:{"comments": 1}}) db.x.update({"a":1}, {$pop:{"comments": -1}}) 基于数组位置的删除,1表示从数组的尾部删除一个元素,-1表示从数组的头部删除一个元素
    $addToSet db.x.update({"a":1}, {$addToSet:{"email": "aa@163.com"}) 该修改器只做用于数组,能够向数组中添加一个值,若数组中已经有了该值,则添加失败
    $each db.x.update({"a":1}, {$addToSet:{"email": {$each: ["1", "2", "3"]}}) 能够遍历出数组中的每一个值,一般与$addToSet搭配使用,完成多个值得添加,若是存在不添加
    $pull db.x.update({"a":1}, {$pull:{"email": "1"}}) 指定数组中的具体元素进行删除,若匹配到多个值,匹配多少删除多少
    $数组定位符 db.x.update({"comments.author": "jhon"}, {$set:{"comments.$.author": 'lili'}}) 定位符只匹配第一个匹配到的文档

    八、查询

    8.一、指定键返回查询

    • 查询使用find函数或者findOne函数
    • 查询返回指定字段,也就是查询指定键
    • db.blog.find({"a":2}, {"ss":1, "wo": 0}),当匹配到包含{"a":2}的文档后,只返回"_id" 和"ss"两个键,"_id"是默认返回的,其中1表示真,0表示假

    8.二、条件查询

    命令 用法 做用
    $gt db.users.find({"age": {"$gt": 20}}) 查询users集合中年龄大于20的文档
    $gte db.users.find({"age": {"$gte": 20}}) 查询users集合中年龄大于等于20的文档
    $lt db.users.find({"age": {"$lt": 20}}) 查询users集合中年龄小于20的文档
    $lte db.users.find({"age": {"$lte": 20}}) 查询users集合中年龄小于等于20的文档
    $ne db.users.find({"username": {"$ne": "andy"}}) 查询users集合中用户名不等于andy的文档
    $or db.users.find({"$or": [{"age": 20},{"username": "andy"} ]}) $or 键对应的值是一个数组,知足数组中任何一个条件的文档都会被查找出来,可做用于不一样的键
    $in db.users.find({"age": {"$in": [12 ,10, 22]}}) $in键对应的值是一个数组,知足数组中任何一个条件的文档都会被查找出来,可是它只做用于同一个键
    $nin db.users.find({"age": {"$nin": [12 ,10, 22]}}) $nin键对应的值是一个数组,不知足数组中任何一个条件的文档都会被查找出来,它也只做用于同一个键
    $mod db.users.find({"age": {"$mod": [5, 1]}}) $mod表示取模运算,运算完成后在做为查询条件,它对应的值是一个数组,该数组只有两个值且有顺序,第一个表示除数,第二个表示余数,在这里表达的意思是,找出年龄除以5后余数为1的文档
    $not db.users.find({"$not":{"age": {"$mod": [5, 1]}}}) $not是元条件查询,即做用其余条件查询之上,例如他与$mod取模运算结合使用,表示取非
    $existe db.users.find({"x":{"$existe": true}}) $existe判断该键是否真实存在,存在则显示出来
    /joy/i db.users.find({"username": /joy/i}) 这里是利用正则表达式去匹配所查询文档的某个键对应的值,i表示不区分大小写

    $where 自定义查询

    db.stu.find({
        $where:function() {
            return this.age>30;}  // this 表明当前查询的文档,找出年龄大于30岁的文档
    })

    8.三、数组查询

    8.3.一、$all
    • 建立以下集合并加入三条文档:

    db.fruit.insert({"_id": 1, "fruits": ["banana", "peach", "apple"]})

    db.fruit.insert({"_id": 2, "fruits": ["orange", "kumquat", "apple"]})

    db.fruit.insert({"_id": 3, "fruits": ["banana", "cherry", "apple"]})

    • {"$all": ["banana", "apple"]},做用于数组,

    使用db.fruit.find({"fruits": {"$all" : ["banana", "apple"]}}),执行结果是数值fruits中只要包含有"banana"和"apple"元素的文档,所有返回,忽略数组中元素的顺序

    • 特殊用法

    {"fruits": {"$all" : ["banana"]}}和{"fruits":"banana"},这两条查询效果是同样的

    • 基于数组下标的查找

    好比:db.fruit.find({"fruits.2":"apple"}),只要数组中指定位置的元素匹配正确,就会返回结果

    8.3.二、$size
    • 查询固定数组长度的文档

      • 用法:db.fruit.find({"fruits": {"$size": 3}})
      • 不能配合其余条件命令使用,例如$gt,而实际生产中,老是须要咱们去查找数组范围的文档
    • 在文档中建立一个size的字段来专门描述数组的长度,变相的经过size的值来范围查找

      • 例如上文:增长一个size字段,db.fruit.update({"_id": 1}, {"$inc": {"size": 3}})
      • 增长数组的内容时,同时增长size的值
    db.fruit.update({"_id": 1}, {"$push" : {"fruits": "pear"}, "$inc" : {"size": 1}})
    • 最后就能够进行范围查找了
    db.fruit.find({"size": {"$gt": 3}})
    8.3.三、$slice
    • 对查找到的数组进行切片处理,并返回新的切片后的文档

      • 使用$slice必须配合find函数的第二个参数使用,find的第二参数是指定文档中的键返回的,未说起或者对应值为0,将不会被返回,当使用$slice后,即便不说起文档中的其余键一样会返回
    db.fruit.find({"_id" : 1}, {"fruits": 1})
    >{ "_id" : 1, "fruits" : [ "banana", "peach", "apple", "pear"]}  # 这里_id默认返回
    # 若是将_id的值变为0,则不会被返回
    db.fruit.find({"_id" : 1}, {"fruits": 1, "_id": 0})  # 数字表明真假
    >{"fruits" : [ "banana", "peach", "apple", "pear"]}
    # 当对返回的键使用切片后$slice,文档中全部的键默认都会返回
    db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}})
    >{ "_id" : 1, "fruits" : [ "banana", "peach", "apple" ], "size" : 4 }
    • 对数组正向切割

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": 3}}), $slcie对应的值是正数便可,获得数组的前三个元素

    • 对数组反向切割

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": -3}}), $slcie对应的值是负数便可,获得数组的后三个元素

    • 对数组指定范围切片

    db.fruit.find({"_id": 1}, {"fruit": {"$slice": [1, 3]}}),$slice对应的值为数组,该数组表示你要操做的数组下标

    ,获得结果:{ "_id" : 1, "fruits" : [ "peach", "apple", "pear" ], "size" : 4 },包含起始和结束下标

    8.四、查询内嵌文档

    • 在mongodb中文档的表现形式,像极了javascript中的对象,因此能够经过对象.属性的方法,来访问MongoDB中的内嵌文档,但也能够匹配整个内嵌文档
    • 方法一:若有文档

    {"name": {"first": "Joe", "last": "Schmoe"}, "age": 27},在集合people中

    db.people.find({"name": {"first": "Joe", "last": "Schmoe"}}),这里能够找到有这个内嵌文档的文档,可是有一个缺点,就是查询条件必须匹配整个内嵌文档,不然就会匹配失败,同时顺序也不可以错,也就是要求精确匹配

    • 方法二:经过对象.属性的方法来访问,就不存在限制了

    db.people.find({"name.first": "Joe", "name.last": "Schmoe"}),这里就要求精确匹配了

    • $elemMatch

    将限定条件进行分组,仅当须要对一个内嵌文档的多个键操做时才会用到

    db.blog.find({"comments": {"$elemMatch": {"author": "joe", "score": {"$gte": 5}}}})

    九、排序、分页和跳过

    9.一、排序sort

    • 使用方法:db.collection.find().sort({"username": 1})
    • 返回结果按升序排列,同时能够设置多个键排序

    db.collection.find().sort({"username":1, "age": -1})

    先以username升序排列,若username相同,则按照age降序排列

    9.二、分页limit

    • 使用方法:

    db.collection.find().limit(20),表示每页返回20条数据

    9.三、跳过skip

    • db.collection.find().skip(20),跳过前20个数据

    组合实现分页查询

    • db.collection.find().limit(20).sort({"age": -1})

    按照年龄从大到小取出前二十条文档

    • db.collection.find().limit(20).skip(20).sort({"age": -1})

    跳过前20条,取后20条的结果

    十、建立索引

    • 方法:db.users.ensureindex({"username": 1})

    十一、游标对象

    使用find函数返回的对象能够赋值给一个变量,这个变量就能够理解为是一个游标对象

    游标对象属性 :可迭代(iterable)

    游标对象方法 :hasNext()判断是否还有下一条数据

    next()获取下一条数据

    十二、聚合函数(aggregate)

    12.一、count函数

    db.stu.count() # 返回fruit集合中的总文档数

    现有以下集合mycol:

    { "_id" : 1, "name" : "tom", "sex" : "男", "score" : 100, "age" : 34 }
    { "_id" : 2, "name" : "jeke", "sex" : "男", "score" : 90, "age" : 24 }
    { "_id" : 3, "name" : "kite", "sex" : "女", "score" : 40, "age" : 36 }
    { "_id" : 4, "name" : "herry", "sex" : "男", "score" : 90, "age" : 56 }
    { "_id" : 5, "name" : "marry", "sex" : "女", "score" : 70, "age" : 18 }
    { "_id" : 6, "name" : "john", "sex" : "男", "score" : 100, "age" : 31 }

    12.二、$group,$sum

    db.stu.aggregate({$group:{_id: "$sex", Count: {"$sum": 1}}})

    12.三、$group,$push

    db.stu.aggregate(
         {$group:
             {
                _id:"$gender",
                 name:{$push:"$name"}
             }
         }
    )  把全部的数据放到一块儿
    $$ROOT, 把整个文档放到一个数组中
    db.stu.aggregate(
         {$group:
             {
                 _id:null,
                 name:{$push:"$$ROOT"}
             }
         }
    )

    12.四、$match`

    db.stu.aggregate(
         {$match:{age:{$gt:20}}
         )

    12.五、$project

    db.stu.aggregate(
         {$project:{_id:0,name:1,age:1}}
         ) //控制显示的文档键

    12.六、$sort

    db.stu.aggregate(
         {$group:{_id:"$gender",counter:{$sum:1}}},
         {$sort:{counter:-1}}
    )

    12.七、$limit,$skip

    db.stu.aggregate(
         {$group:{_id:"$gender",counter:{$sum:1}}},
         {$sort:{counter:-1}},
         {$skip:1},
         {$limit:1}
    )

    1三、数据库命令(runCommand)

    13.一、distinct函数

    db.runCommand({"distinct": "fruit" , "key": "fruits"})

    runCommand指令表示运行命令,括号内的参数的第一个键为具体的指令,指令所对应的的值是要操做的集合,key对应的是要操做的键。

    distinct所表达的意思是找出集合中某个键对应多少不一样的值,也就是去重。

    13.二、group函数

    • 对文档进行分组,stocks集合中有如下文档:

    db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 03:57:01 GMT-400", "price": "4.23"})

    db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 11:28:39 GMT-400", "price": "4.27"})

    db.stock.insert({"day" : "2010/10/03", "time": "10/03/2010 05:00:22 GMT-400", "price": "4.10"})

    db.stock.insert({"day" : "2010/10/06", "time": "10/06/2010 05:27:58 GMT-400", "price": "4.30"})

    db.stock.insert({"day" : "2010/10/04", "time": "10/04/2010 08:34:50 GMT-400", "price": "4.01"})

    获取到天天最新的股票交易价格

    • 使用数据库命令的模式来执行group命令:
    db.runCommand({"group":{
        "ns": "stock",
        "key": {"day": true},  // 程序执行到这里以后,就已经对集合分组完毕了
        "$keyf": function(X){
            return X.toLowerCase() // 将须要排序的键进行转换,好比进行大小写转换
        },
        "initial":{"time":0},  // 每组文档遍历时候的初始值
        "$reduce":function(doc, prev){
            if(doc.time>prev.time){  // 判断时间大小,更新要显示的最近时间
                prev.time = doc.time;
                prev.price= doc.price;
            }
        },
        "condition": {"day": {"$gt": "2010/10/03"}},// 对分组进行条件限制,必须大于条件时间
        "finalize":function(prev){  //对返回结果作最后的修改,和限定
            ...
        }
    }})

    参数解析

    group:对集合执行的操做,即分组

    ns:须要操做的数据集

    key:以文档中的哪一个键进行分组

    $keyf: 对须要分组的键进行条件转换

    initial: 每组文档的初始化值,也就是最终分完组后显示的字段的初始化值

    $reduce: 对分组后的显示文档作最后的操做,在上述案例中,就是找到那一组文档中时间最新的文档,而后把他的时间和股票交易价格显示到咱们能够看到的结果

    condition: 对分组进行条件限制

    finalize: 对返回的结果作最后的修改

    #### 13.三、findAndModify

    db.runCommand({"findAndModify": "stock", # 操做集合stock

    ​ "query": {"day":{"$gt": "2010/09/30"}}, # 查询条件

    ​ "sort": {"day": -1}, # 排序键

    ​ "remove": true # 是否删除文档true

    })

    #### 13.四、建立固定大小的集合

    db.creatCollection("my_collection",{"capped": true, "size": 100000})

    参数解析

    my_collection:集合名

    capped:表示是否限值集合的大小,true表示限值,false表示不限制

    size:表示集合大小,这里表示100000个字节

    更多技术资讯可关注:gzitcast

    相关文章
    相关标签/搜索