Xu•thus Blog

mongodb安装(Windows和Ubuntu)以及mongodb基本用法

1.介绍和安装

1.1 介绍

MongoDB是一个基于分布式文件存储的数据库,是一个介于关系数据库和非关系数据库之间的产品。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言

1.2 安装

本以为用了Ubuntu就可以不用担心版本问题,结果32bit还是个越不过的坎,当初就是因为mongodb对win7 32bit支持不够友好,所以选择使用Ubuntu,结果我还是太天真,mongodb同样不在支持32bit 的Ubuntu,在官网上已经下载不到32bit的mongodb(哭瞎),于是一顿google加stack overflow,最终还是安装好了

  • 下载mongodb
  • 将下载的压缩包复制到自己的目录下,解压 tar zxvf mongodb-linux-i686-3.2.13.tgz
  • 为了方便,重命名为简短一点的名字mv mongodb-linux-i686-3.2.13.tgz mongodb
  • 余下步骤跟win设置差不多,就是最后设置数据库存储路径的时候需要添加额外的参数, 创建目录mkdir db
  • 路径 cd ./bin
  • ./mongod --dbpath=../db --storageEngine=mmapv1区别就在于最后一行参数
  • 开启mongodb ./mongo

2.基本用法

2.1 浏览数据库(这里以数据库library为例)

  • 切换到已有数据库或者创建新的数据库 use library
  • 查看可用数据库 show dbsshow databases
  • 查看可用集合 show collections
  • 查看当前使用数据库 db
  • 使用集合 db.media(media为集合名)

2.2 集合中插入数据

mongodb使用的是BSON(JSON的二进制)格式存储数据

  • 可以先定义数据,然后在调用insertOne函数插入数据库中,media为集合名,不存在的时候会自动创建

    doc = ({"Type": "Book",
    

    … “Title”: “Definitive Guide to MongoDB”,
    … “ISBN”: “987-1-4842-1183-0”,
    … “Publisher”: “Apress”,
    … “Author”: [“Hows, David”,”Plugge Eelco”,”Membrey, Peter”] })
    db.media.insertOne(doc)
    `

  • 直接使用后insertOne方法插入

    db.media.insertOne({ "Type": "DVD",
    ... "Artist": "Nirvana",
    ... "Title": "Nevermind",
    ... "Tracklist": [
    ... {
    ... "Track": "1",
    ... "Title": "Smells Like Teen Spirit",
    ... "Length": "5:02",
    ... },
    ... {
    ... "Track": "2",
    ... "Title": "In Bloom",
    ... "Length": "4:15",
    ... }
    ... ]
    ... })
    

    2.3 查询数据

    使用find函数

  • 查询出集合总所有数据 db.media.find()

  • 查询特定类型的数据 db.media.find({ Artist: "Nirvana" })
  • 查询特定类型的数据,但指定显示的信息,在指定的显示信息后面加上参数1 db.media.find({ Artist: "Nirvana"}, {Title: 1} ),还可以使用参数0来取反,就是除它以外的所有信息

    2.3.1 使用点号

    使用.查找文档中的内嵌信息,处理数组时代码更加简单。比如找到所有办函了特定歌曲的CD

    db.media.find({"Tracklist.Title": "In Bloom"})
    

    还可以直接写数组中的项,每一项必须精确匹配。比如查询作者的图书列表,(示例中的作者是以数组的形式存在)。

    db.media.find({"Author":"Membrey, Peter"})
    

    下面这条语句没有精确匹配,就就查不到任何内容

    db.media.find({"Tracklist": {"Track": "1"}})
    
    2.3.2 使用函数sortlimitskip
  • sort() 可以对查询结果进行排序,使用参数1或-1将结果按照升序或降序排列,不指定参数的或默认为1,即升序

    db.media.find().sort({Title: 1})
  • limit() 限制返回结果的最大数目,参数为数值,默认或者0则返回所有数据。下面表示只返回集合中的前10个文档
    db.media.find().limit(10)
  • skip() 忽略文档中前n个文档.下面表示忽略文档前20个
    db.media.find().skip(20)
  • 可以连用这些函数,实现分页功能

    db.media.find({ Title: -1 }).limit(10).skip(20)
    2.3.3 获取单个文档

    findOne()limit(1)得到的结果一致,如果获取一个的时候推荐使用findOne()

    db.media.findOne()
    2.3.4 使用聚集命令

    Mongodb包含三个基本的聚集函数count(), distinct(),group()

  • count()返回文档数目

    • 显示集合包含多少个文档 db.media.count()
    • 结合操作符使用 db.media.find({ Publisher: "Apress", Type: "Book" }).count()
  • distinct()获取唯一值

    上面示例查询了指定出版商图书信息的文档数目,但是如果集合总有多本书(实体书和电子书)含有相同标题,实质上他们为同一本书,就可以使用distinct()函数获取唯一值

    插入一本书,只修改ISBN号,其他信息相同

    db.media.insertOne({"Type": "Book","Title": "Definitive Guide to MongoDB","ISBN": "987-1-4842-1183-1","Publisher": "Apress","Author": ["Hows, David","Plugge Eelco","Membrey, Peter"]})
    

    这时数据库中含有两本标题一样的书了

    db.media.distinct("Title")
    

    输出,另一个结果显示为Nevermind

    [ "Definitive Guide to MongoDB", "Nevermind" ]
    

    如果查询ISBN,则会返回两条数据

    db.media.distinct("ISBN")
    

    输出

    [ "987-1-4842-1183-0", "987-1-4842-1183-1" ]
    

    可以接受嵌套键

    db.media.distinct("Tracklist.Title")
    

    输出

    [ "In Bloom", "Smells Like Teen Spirit" ]
    
  • group() 将结果分组

    接受3个参数keyinitialreduce

    `* `key`指定希望使用哪个键对结果进行分组
    * `initial` 为每个以分组的结果提供基数。如果希望返回指定的数字,这个参数就应默认为0
    * `reduce` 把所有类似的条目分组在一起
    `

    比如,希望获取集合中任何类型的所有唯一标题列表,另外,只要发现任何相同的元素,就基于标题将他么添加到同一组

    db.media.group( 
      { 
        key: {Title: true}, 
        initial: {Total: 0}, 
        reduce: function(items, prev) { 
          prev.Total += 1 
        } 
      } 
    )
    

    items, prev参数分别表示正在遍历的当前文档和聚集基数对象,最后结果为

    [
        {
            "Title" : "Nevermind",
            "Total" : 1
        },
        {
            "Title" : "Definitive Guide to MongoDB",
            "Total" : 1
        }
    ]
    
    2.3.5 使用条件操作符

    MongoDB支持大量的条件操作符用于更好的过滤结果。增减一些文档

    db.media.insertOne({"Type": "DVD", "Title": "Matrix, The", "Released": 1999, "Cast": ["Keanu Reeves", "Carrie-Anne Moss", "Laurence Fishburne", "Hugo Weaving", "Gloria Foster", "Joe Pantoliano"]})
    
    db.media.insertOne({"Type": "DVD", "Title": "Blade Runner", "Released": 1982})
    
    db.media.insertOne({"Type": "DVD", "Title": "Toy Story 3", "Released": 2010})
    
  • 执行大于或者小于比较$gt,$lt,$gte,$lte

    • $gt 大于,指定文档中的某个整数必须大于指定的值
      db.media.find({ Released: {$gt: 2000} }, { "Cast": 0 })
    • $gte 大于等于
      db.media.find({ Released: {$gte: 1999} }, { "Cast": 0 })
    • $lt,$lte分别表示小于和小于等于,用法更上面类似
    • 可以结合设置一个范围
      db.media.find({ Released: {$gte: 1999, $lt: 2010} }, { "Cast": 0 })
  • 获取除特定文档之外的所有文档$ne
    返回作者不是Plugge Eelco的所有图书db.media.find({ Type: "Book", Author: {$ne: "Plugge Eelco"}})
  • 指定一个匹配的数组($in, 相反不在数组中的值$nin,用法一致)
    返回发行年份为数组里面的文档信息db.media.find({Released: {$in: [1999,2008,2009]}}, {"Cast": 0})
  • 匹配文档中所有属性($all)
    工作方式与$in类似,区别在与$all要求所有属性都匹配,$in匹配一个就行

    db.media.find({Released: {$in: [1999, 2000]}}, {"Cast": 0})
    

    输出

    { "_id" : ObjectId("5922bb479a45340aa9383932"), "Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999 }
    

    db.media.find({Released: {$all: [1999, 2000]}}, {"Cast": 0})
    

    不会返回任何东西,文档中没有发行年份为2000的,所以不能完全匹配,则没有结果

  • 文档中搜索多个表达式

    在单个查询中可以使用$or操作符搜索多个表达式,将返回满足其中任何一个条件的文档。与$in不同,$or可以同时指定键和值,而不只是指定值

    db.media.find({$or: [{ "Title": "Toy Story 3"}, {"ISBN": "978-1-4842-1183-0"}]})
    

    还可以结合另一个查询参数使用

    db.media.find({"Type": "DVD", $or: [{ "Title": "Toy Story 3"}, {"ISBN": "978-1-4842-1183-0"}]})
    

    先满足第一个条件,在执行第二个

  • 使用$slice获取文档
    该方法可以把数组字段限制为匹配结果的一个数组子集。接受两个参数,第一个参数表示将要返回数据项的总数,第二个为可选参数,如果使用了第二个参数,那么第一个参数将用于定义偏移,第二个参数用于定义限制

    • 返回Cast列表中前3项 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: 3}})
    • 可以通过负数获取后3项 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: -3}})
    • 忽略强两项,并限制返回从某个点开始的3个数据db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: [2,3] }})
    • 忽略最后5项数据,并将结果输出限制4条 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: [-5,4] }})
  • 搜索奇数/偶数$mod
    通过$mod操作符可以搜索由奇数或者偶数组成的特定数据,该操作将把目标值除以2,检查运算余数为0还是为1,余数为0则为偶数,余数为1则为基数
    db.media.find({ Released: { $mod: [2, 0] }}, {“Cast”: 0})

    奇数
    db.media.find({ Released: { $mod: [2, 1] }}, {“Cast”: 0})

    注意:只能处理整数,不能处理包含数组的字符串,比如{Released: “2010”}

  • $size过滤结果
    该操作符可以过滤出文档中数组大小符合条件的结果,比如搜索只含有两首歌曲的CD
    db.media.find({ Tracklist: {$size:2} })
    
  • 返回含有特定字段的对象
    $exists将在特定字段存在或不存在的情况下,返回该对象,比如返回集合中含有键Author的所有文档
    db.media.find({Author: {$exists: true} })

    $existsfalse的时候,则返回所有不含Author的文档
  • 匹配完整数组$elemMatch
    如果集合中有多个文档,其中一些文档包含一些相同的信息,使用$elemMatch可以进行数组完整匹配。
    新增一条数据,和之前那条Nirvana的CD包含相同的曲目”Smells Like Teen Spirit”,只不过现在”Smells Like Teen Spirit”为曲目”5”

    db.media.insertOne({ "Type": "CD","Artist": "Nirvana","Title": "Nirvana","Tracklist": [{"Track": "1","Title": "You Know You're Right","Length": "3:38",},{ "Track": "5","Title": "Smells Like Teen Spirit", "Length": "5:02", }] })
    
    比如查询包含”Smells Like Teen Spirit”的CD,并且曲目为1 使用下面语句,两条结果都会被查询出来
    db.media.find({ "Tracklist.Title": "Smells Like Teen Spirit", "Tracklist.Track": "1" })
    
    使用`$elemMatch`完整匹配
    db.media.find({ Tracklist: { "$elemMatch": { Title: "Smells Like Teen Spirit", Track: "1"} } })
    
  • 指定额外的查询表达式

    除了目前结构化查询语法,还可以使用JavaScript指定的额外的查询表达式

    比如,希望查找集合中发布年份早于1995年的DVD,下面这些都可以

    db.media.find({Type: "DVD", "Released": {$lt: 1995}})
    db.media.find({Type: "DVD", $where: "this.Released < 1995"})
    db.media.find("this.Released < 1995")
    f = function() {return this.Released < 1995}
    db.media.find(f)

2.3.6 使用正则表达式
`db.media.find({Title: /^Matrix*/i})` 待深入研究

2.4 更新数据

2.4.1 使用update()更新

可以接受三个参数criteriaobjNew, options

  • criteria可以用于指定一个查询
  • objNew 指定更新信息,也可以使用操作符来完成
  • options用于指定更新文档时的选项,可选值为upsertmultiupsert表示如果数据存在就更新,不存在就创建。multi可以指定是否应该更新所有匹配的文档,或者只更新第一个文档(默认)

    db.media.updateOne({"Title" : "Matrix, The"}, {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action"}, {upsert: true})
    

    使用上条语句,任何忽略的字段都将被移除(该文档基本被重写)

    如果有多个文件符合条件,并且都需要修改,使用$updateMany$set修饰符

    db.media.updateMany({"Title" : "Matrix, The"}, {$set: {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action" }}, {upsert: true})
    
2.4.2 使用save()命令实现upsert

可添加id值,手动或者自动添加该值,不指定的话,就会认为它是一个插入操作,并将文档添加到集合中

db.media.save({"Title" : "Matrix, The"}, {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action"})
2.4.3 自动更新信息
  • 使用$inc增加值
    该操作符可以为指定的键执行(原子)更新操作,如果字段存在,就将该值增加给定的增量。如果不存在,就创建。
    添加一个新的文档

    db.media.insertOne({"Type": "Manga", "Title": "One Piece", "Volumes": 612, "Read": 520})
     

    假设已经阅读到One Piece漫画的4卷内容,就希望更新文档中已读册数的目录

    db.media.updateOne({"Title": "One Piece"}, {$inc: {"Read": 4}})
     
  • 设置字段值$set

    通过该操作符将某个字段设置成特定值。下面语句将Genre字段的值设置成Sci-Fi

    db.media.updateOne({"Title": "Matrix, The"}, {$set: {Genre: "Sci-Fi"}})
    
  • 删除指定字段$unset

    db.media.updateOne({"Title": "Matrix, The"}, {$unset: {Genre: 1}})
2.4.4 在指定字段中添加某个值$push

使用它可以在指定字段中添加某个字段。如果该该字段是数组,那么该值将被添加到数组,如果该字段不存在,那么该字段的值将被设置成为数组。如果该字段存在,但不是数组,则报错。

<pre>db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$push: {Author: "Griffin, Stewie"}})
</pre>
2.4.5 指定数组中的多个值$each

使用$push操作符可以将值添加到指定数值中,如果希望在给定数组中添加几个不同的值,可以使用$each

<pre>db.media.updateOne({"ISBN": "987-1-4842-1183-0"}, {$push: {Author: { $each: ["Griffin, Stewie", "Griffin, Brian"] } } })</pre>
2.4.6 从数组中删除元素$pop,$pull,pullAll
  • $pop可从数组中删除单个元素,允许删除数组中第1个或最后一个,对应参数分别为1-1
    db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pop: {Author: 1 } })
  • 删除所有指定值$pull
    db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pull: {Author: "Griffin, Stewie" } })
  • 删除数组中多个元素$pullAll
    db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pullAll: {Author: ["Griffin, Stewie", "Griffin, Brian"] } })
2.4.7 以原子方式修改和返回文档findAndModify
接受三个主要操作符
  • &lt;query&gt;用于指定目标文档
  • &lt;sort&gt;用于对多个匹配文档进行排序
  • &lt;operations&gt;用于希望执行的操作

    比如找到搜索的目标文档并在找到之后删除

    db.media.findAndModify({"Title": "One Piece", sort: {"Title": -1}, remove: true})

    修改,并会返回更新之前的文档

    db.media.updateOne({query: {"ISBN": "987-1-4842-1183-1"}, sort: {"Title": -1}, update: {$set: {"Title": "Different Title"}}})

    想要返回更新之后的文档,需要增加new操作符

    db.media.updateOne({query: {"ISBN": "987-1-4842-1183-1"}, sort: {"Title": -1}, update: {$set: {"Title": "Different Title"}}, new: true})
    

2.5 删除数据

  • 删除一个文档 db.media.deleteOne({"Title": "Different Title"})
  • 删除多个 db.media.deleteMany({})
  • 删除整个集合 db.media.drop()
  • 删除数据库 db.dropDatabase()